//因爲併發服務器常常fork很多子進程,子進程終結之後需要
//服務器進程去wait清理資源。如果將此信號的處理方式設爲
//忽略,可讓內核把殭屍子進程轉交給init進程去處理,省去了
//大量殭屍進程佔用系統資源。(Linux Only)
if (pid < 0) // error check.
handle_err();
exit (execl(....)); // child process.
else
if (wait(&ret) < 0)
perror(/"wait/"); //parent process
//在這裏wait,都會得No Such process的錯誤,
//因爲子進程終止後,內核會向父進程發送SIGCHLD
//信號,但是上面已將此信號設爲忽略,實質上由
//init來接收此子進程的處理。
signal(SIGCHLD,SIG_IGN);
這樣,內核在子進程結束時不會產生殭屍進程。這一點與BSD4不同,BSD4下必須顯式等待子進程結束才能釋放殭屍進程。
2)我們調用fork函數派生一個子進程後,當子進程快要結束,會向父進程發送一個SIGCHLD信號,告訴父進程我快結束,趕快調用wait函數,來回收子進程的退出狀態和其他信息。
這就是一種我們通常來預發僵屍進程產出的方法,在父進程接收到SIGCHLD信號後,將默認行爲改爲wait來回收子進程的信息。如果父進程沒有調用wait函數,子進程先於父進程退出,則子進程將成爲殭屍進程。
但是wait函數需要阻塞父進程直到子進程結束爲止,對於併發要求較高的併發服務器,可能就不是很適用。
這裏就引出第二種解決殭屍進程的方法,將殭屍進程交給init進程來領養,回收子進程退出狀態和其他信息。當我們忽略SIGCHLD信號,內核將把殭屍進程交由init進程去處理,能夠省去大量殭屍進程佔用系統資源。
即調用: signal(SIGCHLD, SIG_IGN)