Linux核心棧與使用者棧分析

2021-07-12 06:51:51 字數 1687 閱讀 1605

在每乙個程序的生命週期中,必然會通過到系統呼叫陷入核心。在執行系統呼叫陷入核心之後,這些核心**所使用的棧並不是原先使用者空間中的棧,而是乙個核心空間的棧,這個稱作程序的「核心棧」。

核心棧主要用於程序陷入核心時使用的棧,主要涉及程序切換時儲存使用者態程序資訊(暫存器值,一部分硬體上下文等),以及程序在核心執行時分配空間使用。

程序是動態實體,其生命週期範圍很大。因此核心必須能夠同時處理很多程序,並把程序描述符放在動態記憶體中,而不是放在永久分配給核心的記憶體區。

so,對每個程序,linux都把兩個不同的資料結構緊湊的存放在乙個單獨為程序分配的儲存區域內,如下:

核心棧:核心態的程序堆疊,見下圖。

值得注意的是,這塊儲存區域通常為8192位元組(兩個頁框),並且這8k空間佔據連續的兩個頁框。核心控制路徑使用很少的棧,因此核心棧比較小。

圖中的資料結構均是存放在核心位址空間中,task_struct為程序描述符,也是存放在核心位址空間中,是核心對程序進行管理所使用的資料結構,其中包含了程序幾乎所有資訊。

核心棧的結構比較精巧,核心使用乙個聯合體定義核心棧:

union thread_union ;
其中thread_info中存放了程序/執行緒(核心不大區分程序與執行緒)的一些資料,其中包括指向task_struct結構的指標。陣列stack即核心棧,stack佔據8k/4k(依配置不同)空間,是這個聯合體的主要部分。

thread_info結構從0x015fa000位址開始往上存放,核心棧從0x015fc000位址往下存放。因此核心很容易從esp暫存器的值獲得當前在cpu上正在執行程序的thread_info結構的位址。事實上,如果thread_union大小為8k,則核心遮蔽掉esp的低13位就可以獲得thread_info結構的基位址。

這樣,乙個實際的核心棧的結構將如下圖所示。由於棧總是由高位址向低位址延伸的,所以棧底位於thread_union聯合體的最末端,而thread_info結構則位於thread_union聯合體的開始處,而且所占用的空間比較少。只要不出現核心棧特別大的極端情況,棧與thread_info可以互不干擾。該圖為核心位址空間示意圖。

使用者棧就是應用程式直接使用的棧。如下圖所示,它位於應用程式的使用者程序空間的最頂端。

當使用者程式逐級呼叫函式時,使用者棧從高位址向低位址方向擴充套件,每次增加乙個棧幀,乙個棧幀中存放的是函式的引數、返回位址和區域性變數等,所以棧幀的長度是不定的。

使用者棧的棧底靠近程序空間的上邊緣,但一般不會剛好對齊到邊緣,出於安全考慮,會在棧底與程序上邊緣之間插入一段隨機大小的隔離區。這樣,程式在每次執行時,棧的位置都不同,這樣黑客就不大容易利用基於棧的安全漏洞來實施攻擊。

使用者棧的伸縮對於應用程式來說是透明的,應用程式不需要自己去管理棧,這是作業系統提供的功能。應用程式在剛剛啟動的時候(由fork()系統呼叫複製出新的程序),新的程序其實並不占有任何棧的空間。當應用程式中呼叫了函式需要壓棧時,會觸發乙個page fault,核心在處理這個異常裡會發現程序需要新的棧空間,於是建立新的vma並對映記憶體給使用者棧。

核心棧與使用者棧

核心棧和使用者棧區別 intel的cpu分為四個執行級別ring0 ring3 核心建立程序,建立程序的同時建立程序控制塊,建立程序自己的堆疊 乙個程序有兩個堆疊,使用者棧和系統棧 使用者堆疊的空間指向使用者位址空間,核心堆疊的空間指向核心位址空間。有個cpu堆疊指標暫存器,程序執行的狀態有使用者態...

程序核心棧 使用者棧

1.程序的堆疊 核心在建立程序的時候,在建立task struct的同事,會為程序建立相應的堆疊。每個程序會有兩個棧,乙個使用者棧,存在於使用者空間,乙個核心棧,存在於核心空間。當程序在使用者空間執行時,cpu堆疊指標暫存器裡面的內容是使用者堆疊位址,使用使用者棧 當程序在核心空間時,cpu堆疊指標...

程序核心棧 使用者棧

1.程序的堆疊 核心在建立程序的時候,在建立task struct的同事,會為程序建立相應的堆疊。每個程序會有兩個棧,乙個使用者棧,存在於使用者空間,乙個核心棧,存在於核心空間。當程序在使用者空間執行時,cpu堆疊指標暫存器裡面的內容是使用者堆疊位址,使用使用者棧 當程序在核心空間時,cpu堆疊指標...