26

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

$ 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,如果你第一次设置它,它通常可以工作。问题是当你第二次设置它时,它可能会返回错误)

4

5 回答 5

19

显然,mac os x 的堆栈大小有一个硬性限制,取自http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html ,这已经很老了,我不确定它是否仍然如此,但要设置它只需调用 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
$

我还发现了这个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,它就只能降低而不能提高。

于 2012-11-06T23:59:54.127 回答
6

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

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

确实存在软(用ulimit -sor显示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
于 2016-03-16T10:42:09.030 回答
1

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

于 2012-11-06T05:58:31.530 回答
0

我发现使用/bin/zsh而不是/bin/sh使这个错误消失。

对我来说,错误发生在名为ulimit -s unlimited. 当脚本被解释时/bin/sh(即,#!/bin/sh作为脚本文件的第一行),它报错了。相反,将其更改为 use 时zsh,一切似乎都运行良好。 zsh足够聪明,可以解释unlimited为“给我操作系统允许我拥有的最大限制”,并且一切都按照您的意愿进行。

于 2013-10-29T01:57:39.193 回答
0

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

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

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

于 2021-08-23T07:32:21.950 回答