作業系統中,每個程序會有兩個棧,乙個使用者棧,存在於使用者空間,乙個核心棧,存在於核心空間。
當程序在使用者空間執行時,cpu堆疊指標暫存器裡面的內容是使用者堆疊位址,使用使用者棧;當程序在核心空間時,cpu堆疊指標暫存器裡面的內容是核心棧空間位址,使用核心棧。(通過中斷或系統呼叫進入核心態)
核心棧是記憶體中屬於作業系統空間的一塊區域,其主要用途為:
1)儲存中斷現場,對於巢狀中斷,被中斷程式的現場資訊依次壓入系統棧,中斷返回時逆序彈出;
2)儲存作業系統子程式間相互呼叫的引數、返回值、返回點以及子程式(函式)的區域性變數。
使用者棧是使用者程序空間中的一塊區域,用於儲存使用者程序的子程式間相互呼叫的引數、返回值、返回點以及子程式(函式)的區域性變數。
ps:那麼為什麼不直接用乙個棧,何必浪費那麼多的空間呢?
1)如果只用系統棧。系統棧一般大小有限,如果中斷有16個優先順序,那麼系統棧一般大小為15(只需儲存15個低優先順序的中斷,另乙個高優先順序中斷處理程式處於執行)。
但使用者程式子程式呼叫次數可能很多,那樣15次子程式呼叫以後的子程式呼叫的引數、返回值、返回點以及子程式(函式)的區域性變數就不能被儲存,使用者程式也就無法正常執行了。
2)如果只用使用者棧。我們知道系統程式需要在某種保護下執行,而使用者棧在使用者空間(即cpu處於使用者態,而cpu處於核心態時是受保護的),不能提供相應的保護措施(或相當困難)。
5.程序使用者棧和核心棧的切換
當程序因為中斷或者系統呼叫而陷入核心態之行時,程序所使用的堆疊也要從使用者棧轉到核心棧。
程序陷入核心態後,先把使用者態堆疊的位址儲存在核心棧之中,然後設定堆疊指標暫存器的內容為核心棧的位址,這樣就完成了使用者棧向核心棧的轉換;當程序從核心態恢復到使用者態之行時,在核心態之行的最後將儲存在核心棧裡面的使用者棧的位址恢復到堆疊指標暫存器即可。這樣就實現了核心棧和使用者棧的互轉。
那麼,我們知道從核心轉到使用者態時使用者棧的位址是在陷入核心的時候儲存在核心棧裡面的,但是在陷入核心的時候,我們是如何知道核心棧的位址的呢?
關鍵在程序從使用者態轉到核心態的時候,程序的核心棧總是空的。這是因為,當程序在使用者態執行時,使用的是使用者棧,當程序陷入到核心態時,核心棧儲存程序在核心態執行的相關信心,但是一旦程序返回到使用者態後,核心棧中儲存的資訊無效,會全部恢復,因此每次程序從使用者態陷入核心的時候得到的核心棧都是空的。所以在程序陷入核心的時候,直接把核心棧的棧頂位址給堆疊指標暫存器就可以了。
核心棧在kernel-2.6裡面的實現是(kernel-2.6.32):
union thread_union
;
其中thread_size的大小可以是4k,也可以是8k,thread_info佔52bytes。
當核心棧為8k時,thread_info在這塊記憶體的起始位址,核心棧從堆疊末端向下增長。
每當程序呼叫一次函式,都會在使用者棧中為該函式分配乙個棧幀(stack frame),也稱為呼叫棧(call stack),當該函式返回時又會釋放該棧幀。釋放的棧幀不會從虛擬記憶體中移除,它可以被之後呼叫的函式重新使用,所以棧空間的大小是不會減小的。
由於函式內部呼叫函式時,外部函式的棧幀不會釋放,只有內部函式全部退出了才會繼續執行外部函式並在執行完成的時候釋放外部函式的棧幀,所以,遞迴函式(即函式內部呼叫函式自身)如果遞迴呼叫的層次太多(比如無限遞迴),會分配大量的棧幀,並且不會釋放,直到棧空間不足,無法再分配新的棧幀,這時會報棧溢位(stack overflows)錯誤。所以,必須要合理編寫遞迴函式,使得遞迴函式能夠在達到某些條件時返回,從而釋放棧幀,避免無限遞迴。
棧幀中儲存了傳遞給該函式的引數、該函式中定義的區域性變數、函式的返回值、呼叫該函式的程式計數器副本,以及一些其它重要資訊。這裡有必要解釋下棧幀中的程式計數器副本。
什麼是程式計數器(program counter,pc)?這是cpu中的乙個暫存器,在這個暫存器中儲存了下乙個要執行指令的指標。所以,cpu每執行乙個指令的時候,就會設定這個暫存器使它指向下乙個指令。
核心棧和使用者棧
核心棧和使用者棧區別 intel的cpu分為四個執行級別ring0 ring3 核心建立程序,建立程序的同時建立程序控制塊,建立程序自己的堆疊 乙個程序有兩個堆疊,使用者棧和系統棧 使用者堆疊的空間指向使用者位址空間,核心堆疊的空間指向核心位址空間。有個cpu堆疊指標暫存器,程序執行的狀態有使用者態...
使用者棧和核心棧
1.作業系統中,每個程序會有兩個棧,乙個使用者棧,存在於使用者空間,乙個核心棧,存在於核心空間。2.當程序在使用者空間執行時,cpu堆疊指標暫存器裡面的內容是使用者堆疊位址,使用使用者棧 當程序在核心空間時,cpu堆疊指標暫存器裡面的內容是核心棧空間位址,使用核心棧。3.核心棧是記憶體中屬於作業系統...
使用者棧和核心棧的區別
乙個程序有兩個堆疊,使用者棧和系統棧 為何要設定兩個不同的棧?共享原因 核心的 和資料是為所有的程序共享的,如果不為每乙個程序設定對應的核心棧,那麼就不能實現不同的程序執行不同的 核心棧是系統執行在核心態的時候使用的棧,使用者棧是系統執行在使用者態時候使用的棧。當程序由於中斷進入核心態時,系統會把一...