wait函数和waitpid函数

1、wait函数

   当一个进程结束时,会关闭所有的文件描述符,释放所有的内存空间,但依然保存其PCB,内核在PCB中保存着一些信息。
如果是正常退出,则会保存退出状态。
如果是异常终止,则保存是哪个信号终止了该进程。
父进程通过调用wait()或者waitpid()函数,来获取这些信息,之后彻底清除改进程。
只有失败返回值 -1 .
    父进程调用wait函数可以回收子进程终止信息,该函数有三个功能:
① 阻塞等待子进程的退出
② 回收子进程的残留资源
③ 获取子进程的结束状态(退出原因)
在这里插入图片描述
当一个进程终止是,操作的系统的隐式回收机制会
①关闭所有文件描述符
②释放用户空间分配的内存,pCB仍然存在,并保存改进程的退出状态

wait 使用传出参数的status来保存今后才能退出的状态,进一步借用宏函数判断进程终止的原因。可分为如下三组

  1. WIFEXITED(status) 为非0	→ 进程正常结束
    WEXITSTATUS(status) 如上宏为真,
    使用此宏 → 获取进程退出状态 (exit的参数)
    
  2. WIFSIGNALED(status) 为非0 → 进程异常终止
    WTERMSIG(status) 如上宏为真,
    使用此宏 → 取得使进程终止的那个信号的编号。
    
  3.  WIFSTOPPED(status) 为非0 → 进程处于暂停状态
     WSTOPSIG(status) 如上宏为真,
     使用此宏 → 取得使进程暂停的那个信号的编号。
     WIFCONTINUED(status) 为真 → 进程暂停后已经继续运行
    
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(){
  pid_t pid,wpid;
  int status;
  pid =	fork();
  if(pid==0){
	printf("child,my parent=%d,going to sleep 10s\n",getppid());
	//execl("abnormal","abnormal",NULL);
	sleep(60);
	printf("----------------child die---------------------\n");
	exit(76);
  }
  else if(pid>0){
	wpid =wait(&status);
	if(wpid==-1){
	  perror("wait error");
	  exit(1);
	}	 
  } 
  if(WIFEXITED(status)){
	printf("child exit with %d\n",WEXITSTATUS(status));
  }
  if(WIFSIGNALED(status)){
	printf("child killed by %d\n",WTERMSIG(status));
}
  while(1){
	printf("I an parent,pid=%d,myson = %d\n",getpid(),pid);
	sleep(1);
  }
}

2、waitpid函数

作用等于wait,但是可以指定pid,也可以不阻塞。

pid_t waitpid(pid_t pid, int *status, int options);

第一个参数----->指定想要回收的进程 pid

大于 0 回收指定ID的子进程
-1 回收任意子进程(相当于wait)
0 回收和当前调用waitpid一个组的所有子进程 < -1 回收指定进程组内的任意子进程

第二个参数----->传出的参数
第三个参数------>选择阻塞和不阻塞,设置为WNOHANG,且子进程正在运行,为非阻塞。
返回值:
成功:清理进程的pid
失败: 返回-1

注意:一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环。

示例:使用waitpid清理,指定pid的进程

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
int main(int argc,char * argv[] ){
  int n=5,i;//默认创建5个进程
  pid_t p,q,wpid;
  for(i=0;i<n;i++){//父进程的出口
	p=fork();
	if(p==0){
	  break;  //子进程的出口
	}else if(i==2){
	  q=p;//得到第三个孩子的pid
	}
	
  }
  if(n==i){
	sleep(n);
	printf("I am parent,pid = %d ,gid=%d \n",getpid(),getgid());
//① 清理所有的子进程,使用wait
//while(wait(NULL));
//② 回收第三个孩子,清理指定pid,使用waitpid
  waitpid(q,NULL,0);//阻塞
  printf("第三个孩子回收完毕!\n");
  while(1);
//③ 清理所有的子进程 ,第一个参数-1,
/*
  do {
		wpid=waitpid(-1,NULL,WNOHANG);
		if(wpid > 0){
		  n--
		}
		sleep(1);
	  }while(n>0)
*/
  }else{
	sleep(i);
	printf("I am %dth child,pid = %d,gpid=%d\n",i+1,getpid(),getgid());
  }
  return  0;
}

在这里插入图片描述
ps -aux
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值