C

pthread 的預設堆棧大小

  • September 5, 2018

據我了解,Linux 上 pthread 的預設堆棧大小為 16K。我在安裝 64 位 Ubuntu 時得到了奇怪的結果。

$ ulimit -s
8192

還:

pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
printf("Thread stack size = %d bytes \n", stacksize);

Prints
   Thread stack size = 8388608 bytes

我很確定堆棧大小不是“8388608”。有什麼問題?

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

stacksize屬性應定義為創建的執行緒堆棧分配的最小堆棧大小(以字節為單位)。

在您的範例中,堆棧大小設置為 8388608 字節,對應於 8MB,由命令返回,ulimit -s 因此匹配。

pthread_create()描述:

Linux/x86-32上,新執行緒的預設堆棧大小為2 兆字節。在 NPTL 執行緒實現下,如果程序啟動時的 RLIMIT_STACK軟資源限制具有“unlimited”以外的任何值,則它決定了新執行緒的預設堆棧大小。使用pthread_attr_setstacksize (3),可以在用於創建執行緒的 attr 參數中顯式設置堆棧大小屬性,以獲得預設值以外的堆棧大小。

所以執行緒堆棧大小可以通過上面的 set 函式或ulimit系統屬性來設置。對於您所指的 16k,尚不清楚您是在哪個平台上看到的和/或是否為此設置了任何系統限制。

有關這方面的一些有趣範例,請參見pthread_create 頁面此處

實際上,您的虛擬堆棧大小8388608 字節 (8 MB)。當然,很自然地得出這樣的結論是不對的,因為對於每個執行緒來說,在 99% 的情況下它們可能只需要幾個 KB 就可以為其堆棧消耗大量的記憶體。

好消息是您的執行緒只使用它實際需要的**物理記憶體量。**這是您的作業系統通過使用處理器中的硬體記憶體管理單元 (MMU) 獲得的神奇力量之一。這是發生的事情:

  1. 作業系統通過為您的執行緒設置 MMU 的頁表來為您的堆棧分配 8 MB 的虛擬記憶體。這只需要很少的 RAM 來保存頁表條目。
  2. 當您的執行緒執行並嘗試訪問堆棧上尚未分配物理頁面的虛擬地址時,MMU 會觸發稱為“頁面錯誤”的硬體異常。
  3. CPU 核心通過切換到特權執行模式(有自己的堆棧)並呼叫核心內部的頁面錯誤異常處理函式來響應頁面錯誤異常。
  4. 核心將物理 RAM 頁分配給該虛擬記憶體頁並返回給使用者空間執行緒。

使用者空間執行緒看不到任何工作。從它的角度來看,它只是使用堆棧,就好像記憶體一直都在那裡一樣。同時,堆棧會自動增長(或不增長)以滿足執行緒的需求。

MMU 是當今電腦系統硬體的關鍵部分。特別是,它負責系統中的許多“魔法”,因此我強烈建議您更多地了解 MMU 的功能以及一般的虛擬記憶體。此外,如果您的應用程序對性能敏感並處理大量數據,您應該了解 TLB(MMU 的頁表記憶體)的工作原理以及如何重構數據或算法以最大限度地提高 TLB 命中率。

引用自:https://unix.stackexchange.com/questions/127602