6.wait/waitpid:程序回收
阿新 • • 發佈:2018-11-12
0.常用的巨集
1.WIFEXITED(status):為非0 --->判斷程序是否正常結束 WEXITSTATUS(status): 如果WIFEXITED(status)為非0,使用WEXITSTATUS(status) --->[獲取程序退出狀態(exit/return的引數)] 2.WIFSIGNALED(status):為非0--->判斷程序是否被訊號終止 WTERMSIG(status): 如果WIFSIGNALED(status)為非0,使用WTERMSIG(status) --->[取得使程序終止的那個訊號的編號] 3.WIFSTOPPED(status) //為非0--->如果訊號導致子程序停止執行。 WSTOPSIG(status) --->返回導致子程序停止執行的訊號數量 程式碼: if(WIFEXITED(status)) printf("exit value:%d\n",WEXITSTATUS(status)); if(WIFSIGNALED(status)) printf("exit by signal:%d\n",WTERMSIG(status)); if(WIFSTOPPED(status)) printf("程序停止:%d\n",WSTOPSIG(status));
1.wait-阻塞函式
pid_t wait(int* status);
注意:該函式呼叫一次只能回收一個子程序
返回值:
-1:回收失敗,已經沒有子程序
>0:回收是子程序對應的pid
傳出引數:status
判斷子程序是如何死的
正常退出
被某個訊號殺死了
案例1
程式功能: 使用kill -9 子程序pid殺死子程序後,在父程序中呼叫wait函式去回收子程序。 int main(){ pid_t pid=fork(); if(pid<0){ perror("fork fail"); exit(1); } if(pid==0){ while(1){ //子程序一直迴圈printf------>呼叫[kill -9 子程序pid]殺死該程序 sleep(1); printf("child=%d,parent=%d\n",getpid(),getppid()); } } if(pid>0){//父程序:呼叫wait函式,釋放死掉的子程序 printf("parent=%d\n",getpid()); int status; //子程序沒死亡,一直阻塞在wait函式處; //當子程序死亡後,wait函式回收子程序資源&&退出 pid_t w_pid=wait(&status); if(WIFEXITED(status)) printf("exit value:%d\n",WEXITSTATUS(status)); if(WIFSIGNALED(status)) printf("exit by signal:%d\n",WTERMSIG(status)); printf("died child pid=%d\n",w_pid); } return 0; }
2.waitpid
pid_t waitpid(pid_t pid, int *status, int options); 引數: 1.pid pid>0:指定pid的子程序 pid==-1:等待任意一個子程序(等價於wait) —迴圈回收:while((w_pid=waitpid(-1,&status,WNOANG)!=-1) pid==0:當前程序組所有的子程序 pid<0: 2.status:子程序的退出狀態,用法同wait函式(使用巨集) 3.options: 設為0,函式為阻塞 設為WNOHANG,函式為非阻塞 返回值: -1:回收失敗,已經沒有子程序 >0:返回清理掉的子程序ID 如果為非阻塞: =0:子程序處於執行狀態
案例2
父程序產生兩個子程序
子程序1,呼叫ls -l
子程序2,產生段錯誤
父程序,負責使用wait或waitpid回收退出的子程序
int main(){
int i;
pid_t pid;
for(i=0;i<2;i++){
pid=fork();
if(pid==0)
break;
}
if(i==0){
execlp("ls","ls","-l",NULL);
perror("execl");
exit(1);
}
if(i==1){
char* p="Student";
p[5]='K'; //會發生段錯誤
}
if(i==2){ //父程序,回收死亡的子程序
int status;
pid_t w_pid;
/*case1:wait*/
while((w_pid=wait(&status))!=-1){
/*
case2:waitpid
while( (w_pid=waitpid(-1,&status,WNOHANG))!=-1 ){ //迴圈回收
if(w_pid==0) //返回值為0,返回的是正在執行的程序的pid(而不是死亡的程序的pid)
continue;
*/
printf("------wait child's pid = %d\n",w_pid);
if(WIFEXITED(status))
printf("return value=%d\n",WEXITSTATUS(status));
if(WIFSIGNALED(status))
printf("signal value=%d\n",WTERMSIG(status));
}
}
return 0;
}
[[email protected] homework]$ ./test
總用量 16
-rwxrwxr-x. 1 gjw gjw 8696 10月 15 09:59 test
-rw-rw-r--. 1 gjw gjw 812 10月 15 09:59 test.c
------wait child's pid = 8730
return value=0
------wait child's pid = 8731
signal value=11 //訊號11表示的是[段錯誤]