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;                                                                                                                    
  }
[gjw@localhost 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表示的是[段错误]

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/83054034