簡體   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