Liunx — 进程等待 (wait和waitpid函数)

进程等待




 
进程等待就是为了同步父进程和子进程,如把运算放到子进程,赋值放到父进程,可能需要让父进程等待子进程运算结束. 一个进程

终止时会关闭所 有的文件描述符,释放在用户空间分配的内存,但他的PCB还保留着,内核在其中保存了一些信息:如 果是正常终 止则

保存着退出状态,如果是异常退 出则保存着导致该进程终止的信号是哪个. 这个进程的父进程可以调用wait或 waitpid获取这些 信息,

然后彻底消除掉这个进程。我们知道一个进程的 退出状态可以在shall中用特殊变量¥?查看,因为shell 是它的父进程,当 它终止时

Shell 调用wait或waitpid得到它的退出状态同时彻底清除这个进 程。

当一个进程正常或异常终止时,内核就向父进程发送一个SIGCHLD信号。因为子进程终止是一个异步时间,所以发生这种信号发生 也是

内核向父进程发 的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时既被调用执行的函数。对于这种信号 的系统默

动作是忽略它。 而父进程如果 需要处理掉子进程就要调用wait和waitpid命令.

进程的三种基本状态

进程在运行中不断地改变其运行状态。通常,一个运行进程必须具有以下三种基本状态。

就绪状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。

执行状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。

阻塞状态:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多

          种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

那么当父进程调用了wait和waitpid函数后,会发生什么情况呢?

如果其所有子进程都还在运行,则阻塞.

如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止态立即返回.

如果它没有任何子进程,则立即出错返回.

wait/waitpid函数:


头文件:#include<sys/tpes.h>
        #include<sys/wait.h>


wait函数:pid_t wait(int* status)

返回值: 成功返回被等待进程pid,失败返回-1.

参数:输出型参数,获取子进程退出的状态不关心设置空. 如果进程由于接收到SIGCHLD而调用wait,则会期望wait会立即返回.但如

在任意时刻调用 wait,则进程可能阻塞. 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞. 如果

status不是一个空指针,则终止 进程的终止状态就存放它所指的单元内。 如果不关心终止状态,则可将该参数设为空指针.

waitpid函数:
pid_t waitpid(pid_t pid,int *status,int options);

返回值:

1当正常返回时waitpid返回手机的子进程的进程ID

2.如果设置了选项WNOHANG,而调用中waitpid发现没有退出的子进程可手机,贼返回0.

3.如果调用出错返回-1

4.当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程waitpid就会出错返回,这是errno被设置为ECHILD
参数:


1.pid


pid = -1,等待任意个子进程
pid > 0,等待其进程ID与PID相等的子进程
pid = 0 等待其组ID等于调用进程组ID的任意意个子进程
pid < -1 等待其组ID等于PID绝对值的任意子进程

2.status:

WIFEXITED: 若为正常终止子进程的方法返回状态贼为真.
WEXITSTATUS:若WIFEXITED,提取子进程的退出码.

3.options

WNOHANG:若pid指定的子进程还没有结束,则waitpid()函数返回0,不予以等待
若正常结束,则返回该子进程ID.(这里就是我上面说的waitpid的特殊选项)

代码验证:





接下来我们来看看代码的结果:  因为整个过程是一个动态过程,我就把前后结果贴出来就好~

5秒后->


这里就是阻塞等待,接下来我们来看看非阻塞等待。


非阻塞等待:

这个代码我们采用了非阻塞等待,也就是在等待的过程中父进程还在运行自己的代码,然后我们就可以通过程序运行后的结果,

很清晰的看到这个情况,现在看程序运行的结果:


我们很清晰的看到这里根据程序所表示的每隔一秒去看一下,然后再运行自己的程序,这种方式就是一个很节约时间的方式,我

们对待进程等待的理解应该更上一个层次了呢.这里进程等待的知识点大概就是这么多,我们认真理解一定可以熟练地掌握这个知识

点.

相关测试代码:

阻塞等待:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>

int main()
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		printf("%s fork error\n",__FUNCTION__);
		return 1;
	}
	else if(pid == 0)
	{
		//child
		printf("child is run,pid is:%d\n",getpid());
		sleep(5);
		exit(257);
	}
	else
	{
		int status = 0;
		pid_t ret = waitpid(-1,&status,0);// wait 5s
		printf("this is test for wait\n");
		if(WIFEXITED(status)&&ret == pid)
			printf("wait child 5s success,child return code is:%d\n",WEXITSTATUS(status));
		else
		{
			printf("wait child failed,return \n");
			return 1;
		}
	}
}


非阻塞等待:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>

int main()
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		printf("%sfork error\n",__FUNCTION__);
		return 1;
	}
	else if(pid == 0)
	{
		//child
		printf("child is run,pid is: %d\n",getpid());
		sleep(5);
		exit(1);
	}
	else
	{
		int status = 0;
		pid_t ret = 0;
		do
		{
			ret = waitpid(-1,&status,WNOHANG);
			printf("father do other thing\n");
			if(ret == 0)
				printf("child is runing\n");
			sleep(1);
		}while(ret == 0);
		if(WIFEXITED(status)&& ret == pid)
			printf("wait child 5s success,child return cod is:%d\n",WEXITSTATUS(status));
		else{
			printf("wait child failed,return\n");
			return 1;
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值