Как размер стека процесса в linux связан с pthread, fork и exec

У меня вопрос о размере стека процесса в Linux. Является ли размер этого стека определяемым во время привязки и закодирован в файле ELF?

Я написал программу, которая печатает размер стека на pthread_attr_getstacksize(&attr, &stacksize);. И если я запускаю эту программу непосредственно из оболочки, она дает значение около 10 МБ. Но когда я exec это из потока, который принадлежит многопоточной программе, он дает значение около 2 МБ.

Итак, я хочу знать, какие факторы влияют на размер стека процесса, который fork and exec -ed от какого-либо родительского процесса. Можно ли установить размер стека процесса в родительском элементе во время выполнения до fork and exec дочернего?
Спасибо заранее.

Ответы

Ответ 1

Как manpage для pthread_create (3) говорит:

"В Linux/x86-32 размер стека по умолчанию для нового потока составляет 2 мегабайта", если не установлен предел ресурса RLIMIT_STACK (ulimit -s): в этом случае "он определяет размер стека по умолчанию новых потоков".

Вы можете проверить этот факт, извлекая текущее значение RLIMIT_STACK с помощью getrlimit (2), как в следующей программе:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>

int main()
{
    /* Warning: error checking removed to keep the example small */
    pthread_attr_t attr;
    size_t stacksize;
    struct rlimit rlim;

    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr, &stacksize);
    getrlimit(RLIMIT_STACK, &rlim);
    /* Don't know the exact type of rlim_t, but surely it will
       fit into a size_t variable. */
    printf("%zd\n", (size_t) rlim.rlim_cur);
    printf("%zd\n", stacksize);
    pthread_attr_destroy(&attr);

    return 0;
}

Это результаты при попытке запустить его (скомпилированный в a.out) из командной строки:

$ ulimit -s
8192
$ ./a.out 
8388608
8388608
$ ulimit -s unlimited
$ ./a.out 
-1
2097152
$ ulimit -s 4096
$ ./a.out 
4194304
4194304

Ответ 2

В соответствии с man для fork(), дочерний процесс создается с помощью одного потока, который называется fork(). "

Таким образом, размер стека основного потока для дочернего процесса будет размером стека потока, который вызывает fork().

Но когда вызывается одна из функций exec() (в конечном итоге вызывается execve() для выполнения реальной работы), образ процесса заменяется новой программой. В это время стек восстанавливается в соответствии с мягким пределом размера стека (ядро 2.6.23 и новее), которое можно увидеть, вызвав getrlimit (RLIMIT_STACK, & rlimitStruct).

Вы можете управлять этим до вызова exec, установив мягкий предел, используя setrlimit (RLIMIT_STACK, & rlimitStruct) (если вы не пытаетесь увеличить жесткий предел или установить мягкий предел выше жесткого предела).