Linux学习笔记12 ——wait

1,几个概念

  1. 僵死进程(其实就是zombie,僵尸):一个进程已经终止了,但是它的父进程又还没有对他进行善后(比如通过wait获取该子进程的终止状态,释放子进程占用的资源),那么这个已死的进程就叫僵死进程。话说这个都是老子替儿子善后啊,白发人送黑发人。。。。。
  2. 收养:如果一个进程还没终止,但是它的父进程已经终止了,这时候他就成孤儿了。那这个进程终止后岂不无人善后,一定变僵尸??所以系统会自动的让init进程(pid=1)收养这个孤儿,以保证每一个进程都有父进程,不会死后变僵尸。
  3. 退出状态:exit()的输入参数或者return后面跟的数字,就是退出状态。
  4. 终止状态:exit函数会调用_exit()系统调用,在这里退出状态会变成终止状态。后面会介绍一个宏定义WEXITSTATUS,其可以通过终止状态恢复出退出状态。

 

2,函数原型

#include<sys/wait.h>
pid_t wait(int* statloc)

成功,返回子进程的pid;失败,返回0.

函数执行的效果:避免僵尸产生

这个函数在父进程中执行,一直等待其子进程退出。有任意一个子进程退出,wait就返回子进程的pid。并且,如果输入参数statloc不为空指针,则其能获得子进程的终止状态。注意,终止状态并不等于exit的输入参数(退出状态)。终止状态含有退出状态的信息。如果在wait执行前已经有子进程退出了,则wait不用等待,马上获取到该子进程的退出状态并返回。如果一直没有子进程退出,则wait就一直等待,阻塞。

一个典型的使用方法是这样的:

	if (wait(&status) != pid){
		printf("wait error!");
		exit(1);
	} 

3,一些配套的宏定义

我们用wait可以获取到子进程终止时的终止状态status。可是status只是一个int。怎么通过这个int来获取信息呢?

有几个以WIF(我怀疑是wait if的意思。。。)开头的宏定义可用。它们和wait函数在同一个头文件下。

  1. WIFEXITED(status)  , 如果子进程是正常终止,则返回true。这种情况下可以通过WEXITSTATUS(status)获取退出状态
  2. WIFSIGNALED(status),如果子进程异常退出,例如abort退出或分母为0等等,则其为true。此时,可以通过WTERMSIG(status)获取子进程终止的信号编号。同时,有些系统里定义了WCOREDUMP,可以用来确定这个异常退出有没有产生coredump文件。 用法就是WCOREDUMP(status),为true就是产生了。
  3. stop什么的现在不懂,以后再说吧。

4,例子

//获取终止状态的信息,并打印
void pre_exit(int status) 
{
	printf("pre_exit, status = %d\n", status);
	if(WIFEXITED(status))  //正常退出
	{
		printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
	}
	else if (WIFSIGNALED(status)) //异常退出,包括abort()或其他
	{
		printf("abnormal termination, signal number = %d%s\n",WTERMSIG(status),
#ifdef WCOREDUMP
			WCOREDUMP(status) ? "  (core file generated)" : "");
#else
			 "");
#endif
	}
	else if(WIFSTOPPED(status)) //stop??
	{
		printf("child stopped, signal number = %d\n", WSTOPSIG(status));
	}
}

int main(void){
	pid_t pid;
	int status;

	// 1,正常退出
	if((pid = fork()) < 0 )	{ //小于0代表fork出错
		printf("fork error!");
		exit(1);
	} else if (pid == 0) { //等于0代表子进程
		exit(7); //exit的输入参数为退出状态
	}

	//用wait获取子进程的退出状态,获取不到就阻塞,一直等着
	//如果子进程已经终止了,那它马上就能获取到,马上返回
	//返回值为子进程的pid
	if (wait(&status) != pid){
		printf("wait error!");
		exit(1);
	} 
	pre_exit(status);

	// 2, abort
	if((pid = fork()) < 0 )	{
		printf("fork error!");
		exit(1);
	} else if (pid == 0) {
		abort(); //用abort终止子进程
	}

	if (wait(&status) != pid){
		printf("wait error!");
		exit(1);
	} 
	pre_exit(status);

	//3, 分母为0
	if((pid = fork()) < 0 )	{
		printf("fork error!");
		exit(1);
	} else if (pid == 0) {
		status /= 0; //这个异常会导致子进程退出
	}

	if (wait(&status) != pid) {
		printf("wait error!");
		exit(1);
	} 
	pre_exit(status);

	//父进程退出
	exit(0);

}

执行效果是:

➜  code ./study_linux                                       
pre_exit, status = 1792
normal termination, exit status = 7
pre_exit, status = 134
abnormal termination, signal number = 6  (core file generated)
pre_exit, status = 136
abnormal termination, signal number = 8  (core file generated)

可以看到,

第一次,正常退出,退出状态就是我们传递给exit的参数7。

第二次,abort退出,会发出SIGABRT信号,也就是6;

第三次,分母为0,crash,信号为8
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值