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

对于C或Ruby程序,如何在Mac OS X上使用ulimit或每个进程更改堆栈大小?,c,ruby,stack,ulimit,C,Ruby,Stack,Ulimit,似乎为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可能

似乎为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的内存,如果与一个进程可以使用的内存相比,8MB的内存非常小,有时甚至高达2GB

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


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

系统默认堆栈大小因内核的不同版本而异。我的10.7是16384,因此我的Mac接受ulimit-s16384。您可以尝试
sysctl kern.stack\u size
并显示只读堆栈大小。我的号码是16384。
您可以参阅这篇技术文章,了解如何更改C程序的默认堆栈大小。对于Ruby,因为它是一种脚本语言,所以在链接Ruby解释器时必须扩大其堆栈大小。
除了具有非常深的函数调用或递归,或者在堆栈中分配非常大的数组和对象之外,您的程序不应该有巨大的堆栈空间。相反,使用堆或动态分配可以按照您的意愿使用多达2GB的RAM。

显然,mac os x的堆栈大小有一个硬限制,这是理所当然的,而且我不确定它是否仍然是真的,但要设置它,只需调用ulimit-s hard,它的65532。大约65兆

我在雪豹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
$
我也发现了这一点,虽然我还没有测试过,所以不能说太多

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

下面是一个快速教程:

#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
$
#包括
#定义字节数10000000//10兆左右
无效测试()
{
char stack_data[字节数];//在堆栈上分配。
char*heap\u data=malloc(字节数);//指针(heap\u数据)位于堆栈上,实际数据位于堆上。
}
int main()
{   
test();
//此时,堆栈数据[字节数]和*堆数据已被删除,但malloc(字节数)仍然存在。
//根据调用约定,main或test负责重置堆栈。
//在包括gcc在内的大多数编译器上,调用方(main)是负责的。
返回0;
}
$ulimit-a
...
堆栈大小(千字节,-s)8192
...
$gcc m.c
美元/年
分段故障
$ulimit-s难
美元/年
$
ulimit只是临时的,您必须每次更新它,或者更新相应的bash脚本以自动设置它


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

我发现使用
/bin/zsh
而不是
/bin/sh
可以消除这个错误


对我来说,错误发生在一个名为
ulimit-s unlimited
的shell脚本中。当脚本被
/bin/sh
解释时(即,将
#!/bin/sh
作为脚本文件的第一行),它会返回此错误。相反,当将其更改为使用
zsh
时,一切似乎都正常
zsh
非常聪明,将
unlimited
解释为“给我操作系统允许的最大限制”,一切都按照您的意愿运行。

在我看来,公认的答案并不完全正确,会导致误解,更具体地说,最后一句话是不正确的

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

确实存在软(可通过
ulimit-s
ulimit-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

我还想知道为什么它必须在链接时间而不是执行时间执行,如果Ruby真的创建了一个具有堆栈大小的新线程来运行Ruby程序,那么Ruby可能可以使用命令行
Ruby--stack size 16384 foo.rb
Yes来设置堆栈大小。我的操作系统接受
ulimit-s32767
(我认为ulimit的默认值是无限的,但是操作系统内核有默认的大小)。但一旦设置了该值,就不能设置比以前更大的值。否则,将显示错误消息“operation not Allowed”(操作不允许)。在链接时间中设置的默认堆栈大小是合理的,因为当操作系统加载可执行文件时,内核必须在跳入程序之前做好一切准备。链接时间选项以Mach-O可执行文件格式标记堆栈大小,OS/内核可以看到为可执行环境生成不同堆栈大小的选项。Ruby可以为它的新线程创建不同的堆栈大小,但是运行
Ruby
本身的第一个和默认堆栈是由操作系统和链接时间选项决定的。我想知道这个错误是否与。ulimit堆栈大小只能在设置后降低,我已经尝试回答了所有问题,如果您有任何其他问题,请告诉我。是的,如果应用程序占用千兆的内存,它们