2011-12-12 56 views
2

我想了解堆棧分配和對齊如何在具有gcc的Linux x86_64系統上使用pthread以及系統存儲在堆棧上的數據如何工作。我知道你可以使用pthread_attr_setstack配置堆棧內存。我已經在測試程序,將執行以下操作完成的:什麼系統數據存儲在堆棧上

1)遞歸地調用自身,並且更新在所述堆棧

2)上分配打印出第一陣列元素的值未初始化數組,最後一個元素和rsp

從這我已經能夠觀察rsp如何遞增(在我的測試程序中,我注意到一些遞歸調用由編譯器內聯)。我也已經看到,添加TLS內存(使用__thread變量)會導致rsp的第一個值更低。所以它看起來像TLS變量分配在堆棧的頂部。

但是,我不確定的是還有什麼。在我看來,堆棧的第一頁以某種方式爲系統保留,因爲我分配的堆棧變量沒有在該區域中結束。即使我不使用任何__thread變量,我實例化的變量似乎不會分配到第一頁(我設置堆棧內存以便頁面對齊)。

所以我的問題是:除了TLS數據和堆棧變量之外,還有什麼,如果有的話,是在堆棧上的pthread?

回答

4

在Linux NPTL上:

堆棧的最頂端包含TCB。這也被稱爲struct pthreadpthread_t。這是一個有點毛茸茸的,由於所有的怪異的glibc系統特定的定義,但基本上它包含喜歡的東西:

  • 的TLS頭(這部分不包括實際TLS值)
  • 各種標誌
  • 一鏈表用於跟蹤緩存堆疊
  • TID(和堆棧中使用的標誌)
  • PID
  • 魯棒互斥跟蹤信息
  • pthread_cleanup和堆棧展開信息
  • 取消狀態
  • 更標誌
  • 一定數量使用pthread_setspecific TLS插槽 - 如果你超過這個數字,其餘的都在堆上分配
  • 各種鎖
  • 跟蹤信息pthread_join
  • 線程的返回值
  • 調度策略(從線程屬性)
  • 起動程序和線程參數
  • 堆棧大小跟蹤數據
  • 等等等等

這主要是初始化在pthread_create__pthread_create_2_1nptl/pthread_create.c如果你在eglibc源沿着以下),之後將新線程實際上開始運行。

TCB下面是靜態分配的__thread變量 - 或者至少是鏈接器在啓動時可以識別的變量。動態鏈接器初始化鏈接器映射中的l_tls_offset字段,以告知NPTL代碼要預留多少空間。請注意,程序啓動後加載的庫不會成爲其中的一部分 - 有關詳細信息,請參閱__thread ABI spec

__thread以下的變量是堆棧。這個堆棧的頂部是start_thread()代碼,所以它在實際執行用戶代碼之前仍然是一種方式(但不會太多)。

0

如何堆棧分配和調整工作與在Linux x86_64的並行線程

「堆棧」中的子線程真的只是一個內存塊,通常malloc分配(其內部可以通過mmaping實現一個匿名區域),儘管你可以使用原始堆棧區域本身,只要它在線程的生命週期內保持有效,例如

char foo[2<<20]; 
pthread_attr_t attr; 
pthread_t tid; 

pthread_attr_init(&attr); 
pthread_attr_setstack(&attr, foo, sizeof(foo)); 
pthread_create(&tid, &attr, func, NULL); 
pthread_join(tid, NULL);