繁体   English   中英

如何在 Mac OS X 上使用 ulimit 或每个进程为 C 或 Ruby 程序更改堆栈大小?

[英]How to change the stack size using ulimit or per process on Mac OS X for a C or Ruby program?

似乎为 C 程序或 Ruby 程序(使用 C 堆栈)设置堆栈大小的推荐方法是在 Bash shell 中使用ulimit 。但是

$ ulimit -s
8192

$ ulimit -s 16384
-bash: ulimit: stack size: cannot modify limit: Operation not permitted

而且sudo也没有帮助。 有没有办法将其设置为 16MB、32MB 或 64MB? 我认为应该有一种方法可以在每次程序调用时设置它,而不是同时设置系统范围的参数?

现在8192可能意味着 8MB,如果与一个进程可以使用的内存量(有时高达 2GB 的 RAM)相比,这是非常小的。

更新说明: ulimit -a可以显示其当前值)。

更新 2:实际上ulimit -s <value>似乎是每个 shell,如果你第一次设置它,它通常会起作用。问题是当你第二次设置它时,它可能会返回错误)

显然,对于mac os x的堆栈大小有一个硬性限制,取自http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html,这已经很老了,我不确定它是否是仍然是真的,但设置它只是调用ulimit -s hard,它的65532.或大约65 megs。

我对雪豹进行了一些测试,10.6.8,看起来确实如此。

$ ulimit -a
...
stack size              (kbytes, -s) 8192
...
$ ulimit -s 65533
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -s 65532
$

我也发现了这个http://linuxtoosx.blogspot.com/2010/10/stack-overflow-increasing-stack-limit.html虽然我还没有测试过,所以不能真正说出来。

当应用程序消耗通常从堆中获取的内存时,堆栈通常为本地自动变量保留,这些变量存在的时间相当于函数调用的生命周期,堆是大多数持久数据存在的地方。

这是一个快速教程:

#include <stdlib.h>

#define NUMBER_OF_BYTES 10000000 // about 10 megs
void test()
{
   char stack_data[NUMBER_OF_BYTES];          // allocating on the stack.
   char *heap_data = malloc(NUMBER_OF_BYTES); // pointer (heap_data) lives on the stack, the actual data lives on the heap.
}

int main()
{   
    test(); 
    // at this point stack_data[NUMBER_OF_BYTES] and *heap_data have being removed, but malloc(NUMBER_OF_BYTES) persists.
    // depending on the calling convention either main or test are responssible for resetting the stack.
    // on most compilers including gcc, the caller (main) is responssible.

    return 0;
}

$ ulimit -a
...
stack size              (kbytes, -s) 8192
...
$ gcc m.c
$ ./a.out
Segmentation fault
$ ulimit -s hard
$ ./a.out
$

ulimit只是暂时的,您每次都必须更新它,或者更新相应的bash脚本以自动设置它。

一旦设置了ulimit,它只能降低从不升高。

在我看来,接受的答案并不完全正确,导致错过理解,更具体地说,最后的陈述是不正确的。

一旦设置了ulimit,它只能降低从不升高。

确实有软(可用ulimit -sulimit -Ss显示)和硬(可用ulimit -Hs显示)限制。 但是通过ulimit -s设置限制会影响软值硬值。

一旦设置了限制,它只能降低永不升高,但软限制可以降低或提高,只要该值保持低于硬限制。

这将有效:

# base values
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft limit only
$ ulimit -Ss 50
$ ulimit -s
50
$ ulimit -Hs
100
$ ulimit -Ss
50
# raise soft limit only
$ ulimit -Ss 100
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft and hard limit
$ ulimit -s 50
$ ulimit -s
50
$ ulimit -Hs
50
$ ulimit -Ss
50
# then impossible to raise soft limit due to hard limit
$ ulimit -s 100
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -Ss 100
-bash: ulimit: stack size: cannot modify limit: Invalid argument

系统默认堆栈大小因内核的不同版本而异。 我的10.7是16384,因此我的Mac接受了ulimit -s 16384。 您可以尝试sysctl kern.stack_size并显示只读堆栈大小。 我的是16384。
您可以在http://developer.apple.com/library/mac/#qa/qa1419/_index.html上查看此技术文章,了解如何更改C程序的默认堆栈大小。 对于Ruby,因为它是一种脚本语言,所以在链接Ruby解释器时必须扩大其堆栈大小。 除了非常深的函数调用或递归,或者在堆栈中分配了非常大的数组和对象之外,您的程序不应该有很大的堆栈空间。 相反,使用堆或动态分配可以根据需要使用最多2GB的RAM。

我发现用/bin/zsh代替/bin/sh使得这个错误消失了。

对我来说,错误发生在一个调用ulimit -s unlimited的shell脚本中。 当脚本被/bin/sh解释时(即,将#!/bin/sh作为脚本文件的第一行),它会发生此错误。 相比之下,当改变它使用zsh ,一切似乎都很好。 zsh很聪明,可以将unlimited解释为“给我操作系统让我拥有的最大限制”,并且一切都按照你的意愿运行。

内置ulimit控件的所有限制实际上在操作系统 kernel 中实现,因此您应该看到整个系统的 C 接口文档。 这是setrlimit()的 Apple 文档: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setrlimit.2.html

(请注意,该文档的路径似乎是 iPhoneOS,但内容仍然是“Mac OS X”。如果您在本地安装了合适的文档,在终端中运行man setrlimit应该会发出最新的文档。)

新创建的进程从fork()父进程或执行exec()的前一个进程继承限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM