1. 程式人生 > >第一次作業 基於Linux 0.12的進程模型分析

第一次作業 基於Linux 0.12的進程模型分析

schedule 基於 參考 函數 子進程 count node block font

作業內容

挑選一個開源的操作系統,深入源碼分析其進程模型,具體包含如下內容:

  • 操作系統是怎麽組織進程的
  • 進程狀態如何轉換(給出進程狀態轉換圖)
  • 進程是如何調度的
  • 談談自己對該操作系統進程模型的看法

1.操作系統是怎麽組織進程的

  1.1什麽是進程

  程序是一個可執行的文件,而進程是一個執行中的程序實例。Linux操作系統上利用分時技術,可同時運行多個進程。利用分時技術,在Linux操作系統上同時可以運行多個進程。分時技術的基本原理是把CPU的運行時間劃分成一個個規定長度的時間片,讓每個進程在一個時間片內運行。當進程的時間片用完時系統就利用調度程序切換到另一個進程去運行。

  (在Linux內核中,進程通常被稱作任務,而把運行在用戶空間的程序稱作進程)

  1.2 任務數據結構

  內核程序通過進程表對進程進行管理,每個進程在進程表中占用一項,在Linux系統中,進程表項是一個task_struct任務結構指針,定義在頭文件include/linux/sched.h中,其中保存著用於控制和管理進程的所有信息,主要包括進程當前運行的狀態信息、信號、進程號、父進程號、運行時間累計值、正在使用的文件和本任務的局部描述符以及任務狀態段信息。

struct task_struct {  
long state;  //任務的運行狀態(-1不可運行,0 可運行(就緒),>0 已停止)。
long counter ;  // 任務運行時間計數(遞減) (滴答數),運行時間片。  
long priority; // 運行優先數。任務開始運行時counter=priority,越大運行越長。 long signal ; // 信號。是位圖,每個比特位代表一種信號,信號值=位偏移值+1。 struct sigaction sigaction[32] ; // 信號執行屬性結構,對應信號將要執行的操作和標誌信息。 long blocked; // 進程信號屏蔽碼(對應信號位圖)。 int exi t_code; // 任務停止執行後的退出碼,其父進程會來取。 unsigned long start._code; // 代碼段地址。 unsigned long end_code ; //
代碼長度(字節數)。 unsigned long end_data ; // 代碼長度+ 數據長度(字節數)。 unsigned long brk ; // 總長度(字節數)。 unsigned long start_stack ; // 堆棧段地址。 long pid; // 進程標識號(進程號)。 long father; // 父進程號。 long pgrp; // 進程組號。 long session; // 會話號。 long leader ; // 會話首領。 unsigned short uid; // 用戶標識號(用戶id)。 unsigned short euid; // 有效用戶id。 unsigned short suid; // 保存的用戶id。 unsigned short gid; // 組標識號(組id)。 unsigned short egid; // 有效組id。 unsigned short sgid; // 保存的組id。 long alarm ; // 報警定時值(滴答數)。 long utime ; // 用戶態運行時間(滴答數)。 long stime; // 系統態運行時間(滴答數)。 long cutime; //子進程用戶態運行時間。 long cstime; // 子進程系統態運行時間。 long start_t ime ; // 進程開始運行時刻。 unsigned short used_math; // 標誌: 是否使用了協處理器。 int tty; // 進程使用tty 終端的子設備號。-1表示沒有使用。 unsigned short umask; // 文件創建屬性屏蔽位。 struct m_inode * pwd; //當前工作目錄i節點結構指針。 struct m _inode * root ; // 根目錄i 節點結構指針。 struct m_inode * executable; // 執行文件i 節點結構指針。 unsigned long close_on_exec; // 執行時關閉文件句柄位圖標誌。 struct desc_struct ldt [3] ; // 局部描述符表。O-空,1-代碼段cs,2-數據和堆棧段ds&sso struct tss_struct tss; // 進程的任務狀態段信息結構。 }

2.進程狀態如何轉換

  2.1進程所有狀態

  • 運行狀態: 當進程正在被CPU執行,或已經準備就緒隨時可由調度程序執行。進程可以在內核態運行,也可以在用戶態運行
  • 可中斷睡眠狀態:當進程處於可中斷睡眠狀態時,系統不會調度該進程執行。當系統產生中斷或釋放了進程正在等待的資源,或進程收到一個信號,都可以喚醒進程轉換到就緒狀態
  • 不可中斷睡眠狀態: 除了不會因為收到信號而被喚醒,該中斷與可中斷睡眠狀態類似,處於該狀態的進程只有被使用wake_up()函數明確喚醒時才能轉換到可運行的就緒狀態
  • 暫停狀態:當進程收到信號 SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU時就會進入暫停狀態,進程在調試期間接受到任何信號均會進入該狀態。可通過向其發送SIGCONT信號讓進程轉換到可運行狀態

技術分享圖片

  


  進程狀態即進程在生存期內,可處於一組不同的狀態下,(進程狀態保存在進程任務結構的state字段)

  當一個進程的運行時間片用完,系統就會使用調度程序強制切換到其他進程去執行。如果進程在內核態執行時需要等待系統的某個資源,則該進程會自願放棄CPU的使用權,讓調度程序去執行其他進程,該進程則進入睡眠狀態。
  只有當進程從“內核運行態”轉移到“睡眠狀態”時,內核才會進行進程切換操作。在內核態下運行的進程不能被其他進程搶占,且一個進程不能改變另一個進程的狀態。

3.進程是如何調度的

  3.1 調度進程

  內核中的調度程序用於選擇系統中下一個要運行的進程。調度程序可以看作為在所有處於運行狀態的進程之間分配CPU運行時間的管理代碼。Linux進程是搶占式的,搶占發生在進程處於用戶執行狀態階段,在內核執行時是不能被搶占的。

  通過調度函數schedule()函數掃描任務數組,通過比較每個就緒態任務的運行時間遞減滴答計數counter的值來確定當前哪個進程運行的時間最少。哪一個值大,就表示運行時間還不長,於是就選中該進程,並使用任務切換宏函數切換到該進程運行

  3.2 進程切換

   每當選擇出一個新的可運行進程時,schedule()函數就會調用定義在include/asm/system.h 中的switch_to0宏執行實際進程切換操作。該宏會把CPU 的當前進程狀態(上下文) 替換成新進程的狀態。在進行切換之前,switch to()首先檢查要切換到的進程是否就是當前進程,如果是則什麽也不做, 直接退出。否則就首先把內核全局變量current 置為新任務的指針,然後長跳轉到新任務的任務狀態段TSS組成的地址處,造成CPU 執行任務切換操作。此時CPU 會把其所有寄存器的狀態保存到當前任務寄存器TR 中TSS 段選擇符所指向的當前進程任務數據結構的tss 結構中,然後把新任務狀態段選擇符所指向的新任務數據結構中tss 結構中的寄存器信息恢復到CPU 中, 系統就正式開始運行新切換的任務了。

  3. 3 中止進程

  當一個進程結束了運行或在半途中終止了運行,那麽內核就需要釋放該進程所占用的系統資源。這包括進程運行時打開的文件、申請的內存等。

  當一個用戶程序調用exit()系統調用時,就會執行內核函數do exit()。該函數會首先釋放進程代碼段和數據段占用的內存頁面,關閉進程打開著的所有文件,對進程使用的當前工作目錄、根目錄和運行程序的i節點進行同步操作。如果進程有子進程,則讓init 進程作為其所有子進程的父進程。如果進程是- 個會話頭進程並且有控制終端,則釋放控制終端,並向屬於該會話的所有進程發送掛斷信號SIGHUP,這通常會終止該會話中的所有進程。然後把進程狀態置為僵死狀態TASK ZOMBIE。並向其原父進程發送SIGCHLD 信號,通知其某個子進程已經終止。最後do_ exit()調用調度函數去執行其他進程。由此可見在進程被終止時,它的任務數據結構仍然保留著。因為其父進程還需要使用其中的信息。
  在子進程在執行期間,父進程通常使用wait()或waitpid()函數等待其某個子進程終止。當等待的子進程被終止並處於僵死狀態時,父進程就會把子進程運行所使用的時間累加到自己進程中。最終釋放已終止子進程任務數據結構所占用的內存頁面,並置空子進程在任務數組中占用的指針項。

4.談談自己的看法

  第一次接觸window系統之外的系統,感覺信息量很大,要學的有很多,一開始沒有頭緒,但是抓住關鍵字‘進程’,並圍繞進程狀態,可以一步一步發現Linux操作系統的工作方式,因為對此系統了解不多,也沒有接觸別的操作系統源碼,沒有對比,希望在接下來的學習中,會對這門課有更多深入的了解。

5.最後

  參考資料

  linux內核之旅 http://mp.sohu.com/profile?xpt=c29odW1wam00MXNoQHNvaHUuY29t&_f=index_pagemp_1  

  Linux內核完全剖析-基於0.12內核 (趙炯) pdf文檔 下載:http://vdisk.weibo.com/s/dn1igR_OGfuWY

第一次作業 基於Linux 0.12的進程模型分析