1. 程式人生 > >6.wait/waitpid:程序回收

6.wait/waitpid:程序回收

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表示的是[段錯誤]