linux 進程管理與調度(一)


進程結構

  進程在內核的源代碼中以結構體表示,篇幅很長,在此列舉一小段關鍵代碼,可以發現是個雙向鏈表,具體的可以在內核目錄下找一個叫“sched.h”的頭文件。

struct task_struct {
      struct task_struct *real_parent; /* real parent process */
      struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports */
      /*
       * children/sibling forms the list of my natural children
       */
      struct list_head children;      /* list of my children */
      struct list_head sibling;       /* linkage in my parent's children list */
      struct task_struct *group_leader;       /* threadgroup leader */ 

      ……
};

  進程被存放在叫做任務鏈表(tasklist)的雙向循環鏈表中,linux通過slab分配器分配task_struct結構,這樣能達到對象復用和緩存着色(cache coloring)的目的。

  結構體中主要由四部分組成

  1.進程控制塊:進程標志

  2.進程程序塊:可與其他程序共享

  3.進程數據塊:進程專屬空間,用於存放各種私有數據以及堆棧空間

  4.獨立的空間:線程

進程狀態

#define TASK_RUNNING            0
#define TASK_INTERRUPTIBLE      1
#define TASK_UNINTERRUPTIBLE    2
#define __TASK_STOPPED          4
#define __TASK_TRACED           8
/* in tsk->exit_state */
#define EXIT_ZOMBIE             16
#define EXIT_DEAD               32
/* in tsk->state again */
#define TASK_DEAD               64
#define TASK_WAKEKILL           128
#define TASK_WAKING             256

 

 

進程的狀態一共有五種。

1.TASK_RUNNING(運行)--------進程正在執行,或者在隊列中等待執行。這是進程在用戶空間中唯一可能的狀態,也可以應用到內核空間中正在執行的進程。
2.TASK_INTERRUPTIBLE(可中斷)--------進程正在睡眠(也就是他被阻塞)等待某些條件達成。一旦這些條件達成,內核就會把進程狀態設置為運行,處於此狀態的進程也會因為收到信號而提前被喚醒並投入運行。
3.TASK_UNINTERRUPTIBALE(不可中斷)--------除了會因為接收到信號而被喚醒從而投入運行外,這個狀態與可打斷狀態相同。這個狀態通常在進程必須等待時不受干擾或事件很快就會發生時出現。由於處於此狀態的任務對信號不作響應,所以較之可中斷狀態,用的較少。
4.TASK_ZOMBIE(僵死)-------該進程已經結束了,但父進程還沒有調用wait()系統調用。一旦父進程調用了wait(),進程描述符就會被釋放。
5.TASK_STOPPED(停止)---------進程停止執行,進程沒有投入運行也不能投入運行。
 

 

QQ截圖20151127164758

 

 

進程的創建

 

  在linux系統中,所有進程都是PID為1的init進程的后代。內核在系統啟動的最后階段啟動init進程。該進程讀取系統的初始化腳本,並執行其他的相關程序,最終完成系統啟動的整個進程。

image

image 

 

 

 

  進程是系統中基本的執行單位(線程是最小的調度單位),可以利用fork函數創建一個新的進程;

pid_t fork( void )

  fork() 函數不需要參數,但返回兩次,返回值有三種情況:

(1)對於父進程,fork函數返回新的子進程的ID。

(2)對於子進程,fork函數返回0。

(3)如果出錯,fork函數返回-1。

 

   fork函數創建一個新的進程,並從內核中為此進程得到一個新的可用進程ID,之后為這個新進程分配進程空間,並將父進程的進程空間中的內容復制到子進程的進程空間中,包括父進程的數據段+堆棧段,並與父進程共享代碼段。

 

fork函數之后,子進程從等待fork返回開始執行,而不是從頭開始。

  •   注意:子進程完全復制了父進程的地址空間的內容,包括堆棧段+數據段的內容。但是,子進程並沒有復制代碼段,而是和父進程共享代碼段。代碼段是只讀的,不存在修改的問題,因此可以共用。在創建一個子進程后,子進程的地址空間完全和父進程分開,父子進程是兩個獨立的進程。

     

     

      linux環境下提供一個和fork函數類似的函數,可以用來創建一個共用父進程地址空間的子進程。

    pid_t  vfork();

    vfork()與fork()的區別:

    (1)vfork產生的子進程和父進程完全共享地址空間,包括代碼段+數據段+堆棧段。子進程對共享資源進行的修改,也會影響到父進程。

    (2)vfork函數產生的子進程一定比父進程先運行。即父進程調用了vfork函數后會等待子進程運行后再運行。


  • 免責聲明!

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



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