linux內核棧用戶棧切換【轉】


轉自:http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E5%9B%9B%E7%AB%A0%20%E8%BF%9B%E7%A8%8B%E6%8F%8F%E8%BF%B0/4.4.1.htm

4.4.1進程內核棧

每個進程都有自己的內核棧。當進程從用戶態進入內核態時,CPU就自動地設置該進程的內核棧,也就是說,CPU從任務狀態段TSS中裝入內核棧指針esp(參見下一章的進程切換一節)。

X86內核棧的分布如圖4.2所示:

 

 

 

 

     
   
 
     

 

 

 

 

 

         

            圖4.2 內核棧的分布圖

 

   在Intel系統中,棧起始於末端,並朝這個內存區開始的方向增長。從用戶態剛切換到內核態以后,進程的內核棧總是空的,因此,esp寄存器直接指向這個內存區的頂端。 在圖4.2中,從用戶態切換到內核態后,esp寄存器包含的地址為0x018fc00。進程描述符存放在從0x015fa00開始的地址。只要把數據寫進棧中,esp的值就遞減。

 

在/include/linux/sched.h中定義了如下一個聯合結構:

  

    union task_union {

       struct task_struct task;

       unsigned long stack[2408];

};

 

    從這個結構可以看出,內核棧占8kb的內存區。實際上,進程的task_struct結構所占的內存是由內核動態分配的,更確切地說,內核根本不給task_struct分配內存,而僅僅給內核棧分配8K的內存,並把其中的一部分給task_struct使用。

 

task_struct結構大約占1K字節左右,其具體數字與內核版本有關,因為不同的版本其域稍有不同。因此,內核棧的大小不能超過7K,否則,內核棧會覆蓋task_struct結構,從而導致內核崩潰。不過,7K大小對內核棧已足夠。

 

   把task_struct結構與內核棧放在一起具有以下好處:

·      內核可以方便而快速地找到這個結構,用偽代碼描述如下:

task_struct = (struct task_struct *) STACK_POINTER & 0xffffe000

·      避免在創建進程時動態分配額外的內存

·      task_struct結構的起始地址總是開始於頁大小(PAGE_SIZE)的邊界。


免責聲明!

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



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