Как изменить размер стека с помощью ulimit или для каждого процесса в Mac OS X для программы C или Ruby?

кажется, что рекомендуемый способ установить размер стека для программы C или программы Ruby (которая использует стек C) - это использовать ulimit в оболочке Bash. Но!--7-->

$ ulimit -s
8192

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

и sudo не помогло. Есть ли способ установить его на 16MB, 32MB или 64MB? Я думал, что должен быть способ установить его для вызова программы Вместо установки общесистемного параметра?

прямо сейчас 8192 вероятно, означает 8 МБ, что довольно мало, если это по сравнению с сколько процесс может использовать, иногда до 2 ГБ ОЗУ.

(Примечание: ulimit -a может показывать текущие значения).

(обновление 2: это действительно похоже на ulimit -s <value> на оболочку, и если вы установите его в первый раз, он обычно работает. Проблема в том, когда вы устанавливаете его во второй раз, тогда он может вернуть ошибку)

4 ответов


по-видимому, существует жесткий предел размера стека для mac os x, взятый из http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html Конечно, это довольно старый, и я не уверен, что его все еще верно, но установить его просто вызвать ulimit-s трудно, его 65532. или около 65 мегабайт.

Я сделал несколько тестов на snow leopard, 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 установлен его можно только понизить никогда не поднимал.


размер стека системы по умолчанию варьируется от разных версий ядра к ядру. Мой 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. За исключением очень глубоких вызовов функций или рекурсии или очень большого массива и объектов, выделенных в стеке, ваша программа не должна иметь большого пространства стека. Вместо этого использование кучи или динамического распределения может использовать до 2 ГБ ОЗУ, как вы хотите.


как только ulimit установлен, его можно только опустить, никогда не поднимая.

есть действительно мягкие (displayable с ulimit -s или ulimit -Ss) и жесткий (displayable с ulimit -Hs) ограничивает. Но при установке предела через ulimit -s повлияет на soft и жесткий ценностей.

раз жесткий предел установлен его можно только понизить никогда не поднимает, но мягкий предел можно понизить или поднять при условии, что значение остается ниже жесткого предела.

это будет работать:

# 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

я нашел, что с помощью /bin/zsh вместо /bin/sh сделал эту ошибку уйти.

для меня ошибка произошла в сценарии оболочки, который вызвал ulimit -s unlimited. Когда сценарий был интерпретирован /bin/sh (т. е. было #!/bin/sh как первая строка файла скрипта), его вырвало с этой ошибкой. Напротив, при изменении его на use zsh, все, казалось, работает нормально. zsh был достаточно умен, чтобы интерпретировать unlimited как " Дайте мне самый большой предел, который операционная система позволит мне есть", и все работало так, как вы хотели бы.