linux進程的地址空間,核心棧,用戶棧,內核線程


linux進程的地址空間,核心棧,用戶棧,內核線程

地址空間:

32位linux系統上,進程的地址空間為4G,包括1G的內核地址空間,和3G的用戶地址空間。


內核棧:

進程控制塊task_struct中保存了2個page大小的信息。

為什么每一個進程都是用各自的內核棧呢?


引用(http://hi.baidu.com/iruler/blog/item/0c3363f377ccc5c90a46e023.html)“

 

假設某個進程通過系統調用運行在內核態(使用這個全局內核堆棧),此時如果被搶占,發生一次切換,另一個進程開始運行,如果這個當前進程又通過系統調用陷入內核,那么這個進程也將使用這個全局內核堆棧,這樣的話就把以前那個進程的內核空間堆棧給破壞了。 
而如果進程使用獨立的內核棧,就避免了這種情況的發生

 

 

 

 

內核線程:

 

擁有自己獨立內核棧的調度單元,可以參與調度,在內核空間執行。

 

用戶棧:

每一個線程有一個用戶棧,由ss和esp指向。


 

===================================================

                         進程1                                進程2

內核代碼區      kcode (0xc0001000)          kcode (0xc0001000)  

內核棧區          kstack(0xc000F000)          kstack(0xc001F000)

內核棧區          kstack(0xc000D000)          kstack(0xc001D000)

...

內核數據區      kdata  (0xc0003000)          kdata  (0xc0003000)

---------------------------------------------------------------------------------------------

用戶代碼區      ucode  (0x70001000)        ucode (0x70001000) 

用戶棧區          ustack (0x7000F000)        ustack (0x7000F000) 

用戶棧區          ustack (0x7000D000)        ustack (0x7000D000) 

...

用戶數據區      udata   (0x70003000)        udata  (0x70003000) 

===================================================


合理的解釋:

內核1G空間的映射頁表(256個entries*4M)只有一份,n個進程共享(都復制了一份在自己的進程頁表內, 256個內核的entries+768個用戶空間的entries, 總共1024個entries,假定使用4M頁面,並且一開始就全都分配好)。


每個進程用戶空間的這些entries各不相同,比如說,同樣的0x70001000虛擬地址, 進程1指向物理內存0x2000, 而進程2指向0x1000。


每個線程對應的內核棧的虛擬地址不重疊。

thread1's kernel stack  = 0f000,

thread2's kernel stack  = 0d000,

thread3's kernel stack  = 1f000,

thread4's kernel stack  = 1d000

...


思考1:

如果內核棧不是預先分配好的(分 配的意思是指"在內核空間中分出一段一段不重疊空間作為各個線程的棧", e.g. kmalloc調用),那么步入內核態的時候, 壓棧,發生缺頁異常,必須對內核棧占用的這個頁進行換頁,而換頁歷程的調用必然涉及參數的壓棧出棧,而這個時候內核棧沒有就緒,異常發生嵌套,系統出錯!


思考2:

在內核里面做kmalloc是可以的,添加一個entries,關聯一塊物理內存,ok可以用了。


思考3:

如果希望進程共享某一個虛擬內存地址0x80001000的數據, 那么在需要共享的進程p1,p2的頁表中添加1個entries(0x80001000->0x3000)。

另外內核是天然的共享對象,所以才在每一個進程中頁表中設置內核空間頁表的一份拷貝

如果有個家伙特立獨行,創建n個關於內核空間的頁表,指向n個物理內存塊,那么他就需要再在這n個物理內存中"鋪設"n分內核代碼和數據的副本(真是自找麻煩)。


思考4:

內核棧確實不適合共享(一個特殊的內存區域)。怎么辦?像用戶空間棧一樣固定在某一個虛擬地址,安插頁表項entries指向不同的物理內存?顯然不行! 只有一個辦法,在內核空間內分配n個不重疊的空間出來。


思考5:

內核步入的時候最初的“內核棧”並不是真正的內核棧,這個棧是全局的,每個cpu一個,是過渡到真正的內核棧使用的。(http://bbs.pediy.com/archive/index.php?t-87518.html)


思考6:

獨立內核棧的場景, at first 我們分析一下如果共用一個內核棧會出現什么情況,假設有A、B三個進程,A調用系統調用read(1,...)讀按鍵,此時正好又沒有按鍵,
所以A被阻塞在內核,此時內核調度B執行,此時B也調用一個系統調用被阻塞了,而此時按鍵事件到來,進程A被喚醒,A繼續執行。我們想想B進入內核
已經破壞了A進入內核的內核棧,那此時A能正常返回嗎?所以從上面分析A、B肯定是擁有各自的內核棧。此內核棧好像是和task_struct以前分配的
一共分配了3個頁面,除了task_struct占得內存外,其余的就是內核棧。而在x86上這個棧等指針保存在TSS斷的SS0和Esp0中。(http://bbs.chinaunix.net/thread-1930753-1-1.html)


參考資料:

1, 內核棧的使用(http://tech.ddvip.com/2008-09/122095404362368.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM