1. 程式人生 > >linux程序切換,程序上下文,thread_union資料結構(task_union V0.11)

linux程序切換,程序上下文,thread_union資料結構(task_union V0.11)

程序是作業系統中很重要的一個抽象,是對程式的一次執行例項的抽象。每個程序執行在自己的上下中,其上下文包括被程序正文所定義的程序狀態、程序的全域性使用者變數和資料結構、它使用的暫存器的值、儲存在它的程序表項的值以及它的使用者棧和核心棧的內容。當出現執行中程序發生中斷或異常核心會執行中斷或異常處理函式,此時若程序執行在使用者態下,會發生執行態切換,但核心並不產生或排程其他程序來處理中斷或異常。

程序切換會發生在以下兩種情況下:

1)程序因為等待某資源,呼叫sleep_on()進入睡眠狀態,自願放棄CPU的使用權,核心執行schedule()進行排程。

2)當前程序所分配的時間片執行完,並且此時有更高優先順序的程序處於就緒狀態,則核心執行schedule(),執行程序搶佔。

從本質上說,每個程序切換由兩步組成:

1)切換頁全域性目錄以安裝一個新的地址空間,只需要更新cr3頁目錄基址暫存器即可。

2)切換核心態堆疊和上下文資訊。

在Linux中,Linux為每個處理器而不是為每個程序使用TSS,所以程序被切換出去,核心就把其上下文儲存在thread_struct的thread欄位。這個資料結構包括的欄位涉及大部分CPU暫存器,但不包括諸如eax、ebx等通用暫存器,它們被保留在核心態堆疊中。因為所有程序的ss0都是統一的,為核心的ss,核心在初始化的時候,已經將該Tss0設定為自己的ss,因此無需繼續設定ss0,把換入程序的esp0裝入CPU的TSS的esp0欄位。

說到核心態堆疊,這也是一個很重要的資料結構。定義如下:

union thread_union{

   struct thread_info thread_info;  //52byte

   unsigned long stack[2048];  //8K

};

用上面的聯合結構方便的表示一個程序的執行緒描述符和核心棧,可用下圖表示:


實現了在2頁(8K)記憶體區中存放兩種資料結構的方式。由於通常程序核心態堆疊不像使用者態堆疊那樣大,所以不會出現堆疊由於壓入資料太多把thread_info的資料覆蓋的情況。核心從esp暫存器的值可以獲得當前在CPU上執行程序的thread_info結構的地址。