為什麼呼叫fork後需要呼叫wait

2021-10-12 17:18:59 字數 2866 閱讀 6960

就拿linux0.11原始碼分析,從程序2的建立與銷毀舉例子。在這裡貼出的**看不懂的不要緊,我會盡量把流程說清楚,看的懂的那是最好,程式設計師的語言不就是**嗎~ ?

linux核心被載入到記憶體後,就會執行main.c中的main函式,建立程序0,程序0建立程序1,程序1建立程序2

void main(void)		

...}

fokk後就會建立程序1,在子程序中(程序1)fork返回0,為什麼返回0,在這裡說的比較清楚了,

init()由程序1開始執行。

void init(void)

...程序1執行塊···

if (pid>0)

while (pid != wait(&i))

...}

程序1裡面又要執行fork,建立程序2,pid等於0代表的是子程序,大於0代表父程序,所以父程序(程序1)呼叫wait

wait的定義在lib/wait.c檔案中,

#define __library__

#include #include _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)

pid_t wait(int * wait_stat)

_syscall3宣告在unistd.h標頭檔案中。呼叫wait最終呼叫的是sys_waitpid

#define _syscall3(type,name,atype,a,btype,b,ctype,c) \

type name(atype a,btype b,ctype c) \

sys_waitpid找到程序後,就會把程序的狀態設定為中斷等待態,並且重新排程schedule()

程序排程發現程序的狀態時中斷等待狀態,就不會執行該程序,需要等待下一次排程。

int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)

// 若沒有找到符合要求的子程序,則返回出錯碼(子程序不存在)。

return -echild;

}

呼叫wait後,程序1就不再cpu上執行了,此時程序2的狀態時可執行狀態,程序排程後,程序2開始執行,程序2做完自己的事後,就會執行_exit方法,該方法對應就是sys_exit

int sys_exit(int error_code)

do_exit主要事釋放程序占用的頁,然後把自己的狀態改為task_zombie僵死狀態,

tell_father(current->father);通知父程序,給父程序傳送訊號task[i]->signal |= (1<<(sigchld-1));,不是說給父程序發訊號,父程序就會醒來,需要等待下一次程序排程schedule();

int do_exit(long code)

static void tell_father(int pid)

/* if we don't find any fathers, we just release ourselves */

/* this is not really ok. must change it to make father 1 */

printk("bad bad - no father found\n\r");

release(current); // 如果沒有找到父程序,則自己釋放

}

到這裡子程序釋放了自己的占用的記憶體頁資料,但是在程序表裡還占用程序結構,為什麼不釋放完呢,因為父程序還需要知道子程序的返回值,該返回值就存在程序結構體裡,子程序已經是僵死狀態了,這再也不會執行了,等下一次程序排程後,父程序發現收到sigchld訊號,並且是可中斷等待狀態,父程序開始甦醒,接著上次wait**處執行,也就是上面提到的sys_waitpid,該方法找到子程序是task_zombie的程序,釋放子程序占用的程序項。

如果父程序不呼叫wait,子程序結束後,父程序不知道子程序有沒有死,就沒有辦法釋放子程序,雖然子程序釋放了自己占用記憶體頁,但是沒有辦法釋放占用的程序結構體,子程序就會變成殭屍程序。

case task_zombie:

current->cutime += (*p)->utime;

current->cstime += (*p)->stime;

flag = (*p)->pid; // 臨時儲存子程序pid

code = (*p)->exit_code; // 取子程序的退出碼

release(*p); // 釋放該子程序

put_fs_long(code,stat_addr); // 置狀態資訊為退出碼值

return flag; // 返回子程序的pid

避免linux系統呼叫fork後產生僵死程序

殭屍程序 就是 已經結束,但是還沒有清理出去的.用kill 9 pid 也無法殺死.所以程式中應該避免出現殭屍程序.用fork之後,父程序如果沒有wait waitpid 等待子程序的話,子程序完畢後,就成了殭屍程序.但是父程序如果等待wait waitpid的話,就沒法幹別的事情了.尤其在多個子程...

為什麼baseServlet可以呼叫很多方法

servlet會先呼叫service 然後再根據service方法中的定義呼叫doget,dopost等方法 servlet中,service方法是一直存在的,因為最高層的介面servlet 像httpservlet等具體的servlet都是直接或者間接實現了這個介面 裡面就有這個方法,所以不管是怎...

呼叫close 後發生了什麼

我們考慮簡單的客戶端 伺服器通訊的場景,其典型模式為 在tcp層面表現為 我們考慮一些異常情況,客戶端上 選用 unix網路程式設計 第一卷 中的伺服器 客戶端樣例程式。伺服器部分 int main int argc,char ar 伺服器監聽9999埠,新鏈結建立後,發出當前時間,隨後呼叫clos...