2010-02-26 10 views
15

Mam pytanie dotyczące rozmiaru stosu procesu w systemie Linux. Czy ten rozmiar stosu jest określony w czasie powiązania i jest zakodowany w pliku ELF?Jaki jest rozmiar procesu stosu na Linuksie w odniesieniu do pthread, fork i exec

Napisałem program, który drukuje rozmiar stosu przez pthread_attr_getstacksize(&attr, &stacksize);. I jeśli uruchomię ten program bezpośrednio z powłoki, daje to wartość około 10 MB. Ale kiedy I exec to z wątku, który należy do programu wielowątkowego, daje wartość około 2 MB.

Więc chcę wiedzieć, jakie czynniki wpływają na rozmiar stosu procesu, który jest fork and exec -ed od jakiegoś procesu nadrzędnego. I czy możliwe jest ustawienie rozmiaru stosu procesu w rodzica w czasie wykonywania przed fork and exec dzieckiem?
Z góry dziękuję.

Odpowiedz

20

Jak podręcznika dla pthread_create(3) mówi:

Na Linux/x86-32, domyślny rozmiar stosu dla nowego wątku jest 2 megabajtów”, chyba że granica RLIMIT_STACK zasobu (ulimit -s) jest ustawiony: w w tym przypadku "określa domyślny rozmiar stosu nowych wątków".

Można sprawdzić ten fakt pobierania bieżącej wartości RLIMIT_STACK z getrlimit(2), jak w poniższym programie:

#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; 
} 

Są to wyniki, gdy próbuje go uruchomić (skompilowany do a.out) z wiersza poleceń :

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

Oprócz tego, linux automatycznie rozwija stos w razie potrzeby - ale jesteś ograniczony do tych limitów, a także ogranicza dostępną przestrzeń adresową w obszarach, gdzie można uprawiać hazard. – nos

+1

nos, tylko dla głównego wątku, prawda? – osgx

1

Według man page for fork() „proces dziecko utworzone z pojedynczej nitki do jednego, który wywołał widełki()”.

Dlatego rozmiar stosu głównego wątku procesu potomnego będzie wielkością stosu wątku, który wywołuje fork().

Po wywołaniu one of the exec() functions (ostatecznie wywołanie execve() w celu wykonania prawdziwej pracy) obraz procesu zostaje zastąpiony nowym programem. W tym czasie stos jest ponownie tworzony zgodnie z miękkim limitem rozmiaru stosu (jądro 2.6.23 i nowsze), które można zobaczyć, wywołując getrlimit(RLIMIT_STACK, &rlimitStruct).

Ty może kontrolować to przed wywołaniem exec ustawiając ograniczenie miękkie korzystając setrlimit(RLIMIT_STACK, &rlimitStruct) (pod warunkiem, że nie starają się zwiększyć sztywny limit lub ustawić ograniczenie miękkie wyższa niż twardego limitu).