AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 551491
Accepted
Kingsley
Kingsley
Asked: 2019-11-11 20:54:53 +0800 CST2019-11-11 20:54:53 +0800 CST 2019-11-11 20:54:53 +0800 CST

堆栈大小的 ulimit - 每个进程或每个线程限制?

  • 772

所以我们在 Solaris 上有一个程序,它的堆栈空间不足。

在对此进行调查时,我简要了解了堆栈的 ulimit 是什么:

user@solaris-box:~$ ulimit -a
...
stack size              (kbytes, -s) 8192

所以堆栈大小限制为 8 兆字节。但这是整个过程的极限吗?

如果我的进程有 10 个线程怎么办,每个线程只允许 819k 吗?(或它们的一些混合,高达 8MiB?)

我找不到任何关于此的文档。

solaris
  • 1 1 个回答
  • 9570 Views

1 个回答

  • Voted
  1. Best Answer
    Andrew Henle
    2019-11-13T07:41:50+08:002019-11-13T07:41:50+08:00

    概括

    对于主线程,您必须在进程启动之前setrlimit()调用(可能通过使用ulimit),以确保较大的堆栈大小有效。

    对于由进程​​启动的线程,您需要使用pthread_attr_setstacksize(),因为线程堆栈大小完全不受来自/的stack size资源限制的影响。setrlimit()getrlimit()

    代码需要看起来像这样:

    pthread_attr attr;
    pthread_attr_init( &attr );
    
    // 32MB stack size example - should **NOT** hardcode this
    // but get it from an environment variable or property setting
    size_t stacksize = 32UL * 1024UL * 1024UL;
    pthread_attr_setstacksize( &attr, stacksize );
    
    pthread_create( &tid, &attr, start_func, thread_arg );
    

    您可以从当前堆栈大小限制中获取线程堆栈大小:

    struct rlimit limits;
    
    getrlimit( RLIMIT_STACK, &limits );
    size_t stacksize = limits.rlim_cur; // use rlim_max for hard limit
    

    (请注意,如果您使用的是创建自己的线程的库,则该库可能有自己记录的设置线程堆栈大小的方法,例如 OpenMPI。)

    详细解答

    资源限制由ulimit实用程序从命令行设置。

    如果你跑truss -f -a -vall -o /tmp/truss.out /usr/bin/ulimit -a,你会看到

    address space limit (kbytes)   (-M)  unlimited
    core file size (blocks)        (-c)  unlimited
    cpu time (seconds)             (-t)  unlimited
    data size (kbytes)             (-d)  unlimited
    file size (blocks)             (-f)  unlimited
    locks                          (-x)  not supported
    locked address space (kbytes)  (-l)  not supported
    message queue size (kbytes)    (-q)  not supported
    nice                           (-e)  not supported
    nofile                         (-n)  1024
    nproc                          (-u)  29995
    pipe buffer size (bytes)       (-p)  5120
    max memory size (kbytes)       (-m)  not supported
    rtprio                         (-r)  not supported
    socket buffer size (bytes)     (-b)  5120
    sigpend                        (-i)  128
    stack size (kbytes)            (-s)  8192
    swap size (kbytes)             (-w)  not supported
    threads                        (-T)  not supported
    process size (kbytes)          (-v)  unlimited
    

    如果你调查一下/tmp/truss.out,你会看到

    7752:   execve("/usr/bin/ulimit", 0xFFFF80FFBFFFF9E8, 0xFFFF80FFBFFFFA00)  argc = 2
    7752:    argv: /usr/bin/ulimit -a
    7752:   sysinfo(SI_MACHINE, "i86pc", 257)       = 6
    
      much deleted extraneous data (loading shared libraries, etc)...
    
    7752:   getrlimit(RLIMIT_VMEM, 0xFFFF80FFBFFFD4B0)  = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_CORE, 0xFFFF80FFBFFFD4B0)  = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_CPU, 0xFFFF80FFBFFFD4B0)   = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_DATA, 0xFFFF80FFBFFFD4B0)  = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_FSIZE, 0xFFFF80FFBFFFD4B0) = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_NOFILE, 0xFFFF80FFBFFFD4B0)    = 0
    7752:       cur = 1024  max = 65536
    7752:   sysconfig(_CONFIG_CHILD_MAX)            = 29995
    7752:   pathconf("/", _PC_PIPE_BUF)         = 5120
    7752:   pathconf("/", _PC_PIPE_BUF)         = 5120
    7752:   sysconfig(_CONFIG_SIGQUEUE_MAX)         = 128
    7752:   getrlimit(RLIMIT_STACK, 0xFFFF80FFBFFFD4B0) = 0
    7752:       cur = 8388608  max = RLIM64_INFINITY
    7752:   getrlimit(RLIMIT_VMEM, 0xFFFF80FFBFFFD4B0)  = 0
    7752:       cur = RLIM64_INFINITY  max = RLIM64_INFINITY
    7752:   write(1, " a d d r e s s   s p a c".., 942) = 942
    

    我们看到它ulimit使用( getrlimit()and setrlimit()) 库函数来获取/设置资源限制。

    每/页(getrlimit()setrlimit() man注意粗体部分):

    RLIMIT_STACK

    进程堆栈的最大大小(以字节为单位)。系统不会自动将堆栈增长到超出此限制。

    在一个进程中,setrlimit()将增加对堆栈大小的限制,但不会移动当前内存段以允许该增长。为了保证进程堆栈可以增长到限制,必须在执行要使用新堆栈大小的进程之前更改限制。

    在多线程进程中,setrlimit()如果调用线程不是主线程,则对调用线程的堆栈大小限制没有影响。setrlimit()对for的调用RLIMIT_STACK仅影响主线程的堆栈,并且应该仅从主线程进行,如果有的话。

    信号被SIGSEGV发送到进程。如果进程正在持有或忽略 SIGSEGV,或者正在捕获SIGSEGV但尚未安排使用备用堆栈(请参阅参考资料),则在发送之前将设置sigaltstack(2)的处置。SIGSEGVSIG_DFL

    因此,由非主线程的进程创建的线程的堆栈大小不受进程RLIMIT_STACK资源限制的影响。而且您必须在进程启动setrlimit() 之前(在父进程中)调用,以确保任何更大的堆栈大小限制实际上是有效的。

    根据手册页:pthread_create()

    创建的新线程pthread_create()使用stackaddr属性指定的堆栈,堆栈继续属性指定的字节数stacksize。默认情况下,32 位进程的堆栈大小为 1 兆字节,64 位进程的堆栈大小为 2 兆字节(请参阅 参考资料pthread_attr_setstacksize(3C))。stackaddr如果和stacksize属性 都使用默认值,pthread_create()则为新线程创建一个堆栈,其中 32 位进程至少 1 兆字节,64 位进程至少 2 兆字节。(有关自定义堆栈大小,请参阅 NOTES )。

    ...

    笔记

    ...

    用户指定的堆栈大小必须大于 value PTHREAD_STACK_MIN。最小堆栈大小可能无法容纳用户线程函数的堆栈帧start_func。如果指定了堆栈大小start_func,除了最低要求外,它还必须满足要求和它可能依次调用的函数。

    通常很难确定线程的运行时堆栈要求。PTHREAD_STACK_MIN指定执行一个NULL start_func. 堆栈存储的总运行时要求取决于执行运行时链接所需的存储量,以及printf()线程调用的库运行时(as)所需的存储量。由于这些存储参数在程序运行之前是未知的,因此最好使用默认堆栈。如果您知道您的运行时要求或决定使用大于默认值的堆栈,那么指定您自己的堆栈是有意义的。

    • 4

相关问题

  • Solaris 11 上的 Samba4 巨人

  • Solaris 11:两个服务清单!我要一个

  • 我可以在不删除主目录的情况下对用户进行 userdel 吗?

  • 阻止损坏的 NFS 挂载锁定 solaris 11.3 中的目录?

  • 在 Solaris 上;查找、附加到 tar 球并压缩问题

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve