下面通過**,為了觀察,完成同樣的功能,體會三種程序等待方式的區別。
三種等待方式
1.wait、waitpid、忽略sigchild訊號(忽略sigchild訊號只在linux下有效);
2.wait只能進行阻塞等待,waitpid既可以用於阻塞等待,也可以用於非阻塞等待;
waitpid(當waitpid的第三個引數為0時表示阻塞等待,當為wnohang時表示非阻塞等待)
3.wait和waitpid函式都可以獲得程序的退出碼,而忽略sigchild訊號只能防止程序變為殭屍程序並不能獲得程序的退出碼。(所以如果想要獲得程序退出碼,只能採用wait和waitpid函式)。
wait
1.wait函式原型
pid_t wait(int* status)
//引數:status表示被等待程序的退出碼
//返回值:成功返回被等待程序的pid,失敗返回-1
2.使用:
#include
#include
#include
#include
int main()
else if(pid > 0)
else
return 0;
}waitpid
1.waitpid函式原型
pid_t waitpid(pid_t pid, int* status, int options)
//返回值:①正常返回時,返**集到的子程序的pid;②當第三個引數設定為wnohang,當呼叫者發現沒有沒有已退出的子程序可收集(或者子程序還在執行),則返回0;如果呼叫出錯,返回-1.
//引數:pid表示等待指定子程序的pid,如果為-1表示等待任意乙個子程序;status用於獲得子程序的退出碼,options表示採用何種方式等待(阻塞或非阻塞,0表示阻塞,wnohang表示非阻塞)
2.使用
#include
#include
#include
#include
int main()
else if( pid == 0)
//father
while(1)
return 0;
可以發現:wait與wait的使用方法基本一致
注意:呼叫wait或waitpid的次數必須和fork建立子程序的數目一致,如果wait的次數少於子程序的數目,就會導致還有一些子程序任然是殭屍程序;如果wait的次數多於子程序的數目就會導致wait出錯,因為已經沒有子程序需要等待。
sigchild訊號
1.前面我們已經了解到:當子程序退出後,會給父程序傳送乙個sigchild訊號,該訊號的預設處理動作是忽略。
2.父程序可以定義sigchild訊號的處理行為,就可以讓父程序去做其它事,當父程序接收到該訊號時再進行程序等待,就不會造成殭屍程序。
3.那麼我們可以在sigchild訊號的處理函式裡面呼叫wait或waitpid進行等待,這樣就可以讓父程序及時的發現子程序退出,不用一直阻塞,則父程序就可以做其它的事情。
例如:父程序建立子程序,在訊號處理函式裡面呼叫wait:
#include
#include
#include
#include
#include
void handel(int signo)
printf("child exit!\n");
}int main()
else if(pid == 0)
while(1)
return 0;
}
4.在linux下,還可以採用忽略sigchild訊號來解決殭屍程序的問題。
#include
#include
#include
#include
#include
int main()
else if(pid == 0)
while(1)
return 0;
}
執行結果如下:
什麼是殭屍程序和孤兒程序?怎麼避免殭屍程序
孤兒程序 父程序退出,子程序還在執行的這些子程序都是孤兒程序,孤兒程序將被 init 程序 進 程號為 1 所收養,並由 init 程序對它們完成狀態收集工作。殭屍程序 程序使用 fork 建立子程序,如果子程序退出,而父程序並沒有呼叫 wait 或 waitpid 獲 取子程序的狀態資訊,那麼子程...
什麼是殭屍程序和孤兒程序?怎麼避免殭屍程序?
孤兒程序 父程序退出,子程序還在執行的這些子程序都是孤兒程序,孤兒程序將被init 程序 程序號為1 所收養,並由init 程序對他們完成狀態收集工作。殭屍程序 程序使用fork 建立子程序,如果子程序退出,而父程序並沒有呼叫wait 獲waitpid 獲取子程序的狀態資訊,那麼子程序的程序描述符仍...
殭屍程序的危害及避免
由於子程序的結束和父程序的執行是乙個非同步的過程,所以父程序不知道子程序什麼時候結束,這可能導致當子程序結束時父程序太忙而丟失子程序結束時的狀態資訊。於是,unix提供了一種機制保證了只要父程序想要看到子程序結束的資訊,就能看到。這種機制就是 在每個程序退出時,核心釋放所有資源,但扔然保留一定的資訊...