以下部分的代碼示例,來自於Linux內核的0.11版本源碼
在定義進程的數據結構task_struct時,有一個state字段是用來表示進程狀態的,這裡總結了下關於state字段的操作
關於進程的幾個狀態值在sched.h中定義如下
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4
在Linus對state的注釋中,是這樣寫的,state<0為不可運行狀態(可能是初始化時的值,後面將討論)、state=0為運行狀態(就緒也屬於此狀態)、state>0為進程停止運行狀態(不論是進程正處於睡眠或是已經退出終止了)
下面討論對state的字段修改是在哪些地方
[進程初始化時的state字段修改]
首先當一個進程被創建的時候,它的狀態是TASK_UNINTERRUPTIBLE;因為這時它的數據都是從父進程賦值而來的,還沒有設置成自己進程的數據。
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
當進程數據設置完成後,進程變為可運行狀態
p->state = TASK_RUNNING; /* do this last, just in case */
以上者兩部分代碼都是來自fork.c的copy_process函數。在最後設置好了新建進程的state字段後,copy_process函數返回。
[進程退出時的狀態設置]
當進程退出的時候,state字段被設置為TASK_ZOMBIE,在exit.c的do_exit函數中,對當前退出的進程,將其狀態設置成TASK_ZOMBIE.
current->state = TASK_ZOMBIE;
current->exit_code = code;
tell_father(current->father);
schedule();
return (-1);
[父進程等待子進程結束時的狀態設置]
調用waitpid(exit.c文件中)時,掛起調用的進程,直到指定pid的子進程退出或終止或者收到要求終止該進程的信號。。。
在waitpid函數的最後,有一條語句如下
if (flag) {
if (options & WNOHANG)
return 0;
current->state=TASK_INTERRUPTIBLE;
schedule();
這裡的flag=1表示指定等待的pid的進程既沒有終止也不處於僵死狀態。所以,這裡將當前等待的進程設置成可中斷的睡眠狀態。並且重新進行進程調度
[進程調度修改進程的狀態]
在sched.c的schedule函數中
if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
(*p)->state==TASK_INTERRUPTIBLE)
(*p)->state=TASK_RUNNING;
當進程等待的事件發生時,將進程的狀態設置成可運行的狀態
[通過系統調用將進程暫停]
但通過系統調用將進程暫停時,進程的狀態被設置成可中斷的睡眠狀態,然後重新進行進程調度。具體代碼如下(sched.c的sys_pause函數)
int sys_pause(void )
{
current->state = TASK_INTERRUPTIBLE;
schedule();
return 0;
}