2010-02-26 111 views
15

我對Linux上進程的堆棧大小有疑問。這個堆棧大小是否在鏈接時間確定,並在ELF文件中編碼?linux上進程的堆棧大小與pthread,fork和exec有關

我寫了一個程序,它打印的堆棧大小爲pthread_attr_getstacksize(&attr, &stacksize);。如果我直接從一個shell運行這個程序,它會給出大約10MB的值。但是,當我從屬於多線程程序的線程中獲得exec時,它給出了大約2MB的值。

所以我想知道哪些因素會影響一個進程的堆棧大小,這是從某個父進程開始的。是否有可能在孩子的fork and exec之前的運行時間在其父級中設置進程的堆棧大小?
在此先感謝。

回答

20

至於pthread_create(3)手冊頁說:

在Linux/X86-32,對於一個新的線程默認堆棧大小是2兆字節」,除非RLIMIT_STACK資源限制(ulimit -s)設置:在在這種情況下,「它確定了新線程的默認堆棧大小」。

您可以通過getrlimit(2)檢索RLIMIT_STACK的當前值檢查這一事實,如下面的程序:

#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 
+3

除此之外,linux在需要時會自動生成堆棧 - 但是您的目標受限於這些限制,以及可擴展區域中可用地址空間的限制。 – nos 2010-02-26 08:56:05

+1

nos,僅適用於主線程,不是嗎? – osgx 2011-08-25 19:43:18

1

根據man page for fork(),「子進程是使用單個線程創建的 - 即稱爲fork()的子進程」。

因此,子進程的主線程的堆棧大小將是調用fork()的線程的堆棧大小。

但是,當調用one of the exec() functions(最終呼叫execve()做真正的工作)時,過程映像被替換爲新程序。此時,根據堆棧大小軟限制(內核2.6.23及更高版本)重新創建堆棧,可通過調用getrlimit(RLIMIT_STACK, &rlimitStruct)來查看堆棧大小。

可以在調用exec之前通過使用setrlimit(RLIMIT_STACK, &rlimitStruct)(假設您不嘗試增加硬限制或將軟限制設置爲高於硬限制)來設置軟限制來控制此操作。