Linux系统【三】回收子进程

孤儿进程

父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,则称init进程领养孤儿进程。现在好像是用户进程中的system进程。

僵尸进程

进程终止,父进程不进行回收,自己成残留资源(PCB)存放在内核中,变成僵尸进程。

子进程死亡以后会将自己占用的内存(4G)释放,但是会将死亡信息放在自己的PCB中,希望父进程调用得到子进程的死亡信息以后再清除PCB。需要注意的是僵尸进程是不能使用kill命令清除掉的,因为kill命令知识用来终止进程的,而僵尸进程已经终止。这就要求我们手动回收子进程。

这里的僵尸进程特别指的是父进程没有结束而子进程已经结束,如果父进程结束就算我们不手动回收也会自动回收(实际过程是父进程结束以后没有回收的子进程变成孤儿进程被init进程或者system进程回收)

wait函数回收子进程

一个进程在终止时会关闭所有的文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或者waitpid获取这些信息,然后彻底清除这个进程。

shell下一个进程的退出状态可以用特殊变量$?查看,因为shell是他的父进程,当它终止时shell调用wait或者waitpid得到它的退出状态同时彻底清除掉这个进程。

wait函数可以回收子进程终止信息,该函数有三个功能:

  • 阻塞等待子进程退出:如果子进程没有结束父进程不会干其他的事情
  • 回收子进程残留的PCB资源
  • 获取子进程结束状态(退出原因)

一次wait函数只能清除一个子进程

pid_t wait(int *status); 

返回值:如果成功返回子进程ID,如果失败返回-1(没有子进程的话就会报错)

status保存结束状态

  • 进程正常结束
WIFEXITED(status) 为非0说明是正常退出
WEXITSTATUS(status)如果上面宏为真,使用这个宏获取进程退出状态(exit的参数)
  • 进程异常终止(收到信号终止,例如段错误、总线错误、浮点数例外错误)
WIFSIGNALED(status) 为非0,说明程序异常终止
WTERMSIG(status)如果上面宏为真使用此宏 取得使得进程终止的那个信号的编号
  • 进程处于暂停状态
WIFSTOPPED(status) 为非0,进程处于暂停状态
WSTOPSIG(status) 如果上述宏为真,取得使得进程暂停的那个信号的编号
WIFCONTINUED(status) 为真表示进程暂停后已经继续运行

waitpid函数

一次waitpid函数只能清除一个子进程,和wait函数类似

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

第一个参数用于指定需要回收的进程ID,第三个参数可以设置不阻塞回收,即仅仅返回一个状态

pid:

  • 大于0 表示回收的子进程ID
  • -1 表示回收任意子进程(相当于wait)
  • 0 回收当前调用waitpid一个组的任意子进程,在一般情况下和-1相同
  • <-1 回收指定进程组内的任意子进程,-进程组ID,进程组ID可以用ps ajx查看
    options:
  • 当参数为WNOHANG,非阻塞回收,轮询查看
  • 当参数为0的时候,阻塞回收,相当于wait

返回值:

  • 成功返回子进程ID
  • 失败返回-1
  • 如果轮询访问回收子进程的时候子进程没有结束则返回0
    例如:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>

int main(int argc, char* argv[])
{
	int n=5;
	if(argc>2)
	{
		printf("too many arguments\n");
		exit(1);
	}
	else if(argc==2)
	{
		n = atoi(argv[1]);
	}
	int pi;
	pid_t p,q;
	for(pi=0;pi<n;++pi)
	{
		p=fork();
		if(0 == p)
		{
			break;
		}
		else if(3 == pi)
		{
			q = p;
		}
	}
	if(n==pi)
	{
		printf("I am parent,pid = %d\n",getpid());
		//删除单个子进程
		//waitpid(q,NULL,0);
		//循环删除子进程
		//while(-1!=waitpid(-1,NULL,0));
		//非阻塞删除子进程
		pid_t tid;
		do
		{
			tid=waitpid(-1,NULL,WNOHANG);
		}while(tid != -1);
		printf("OK\n");
		while(1);
	}
	else
	{
		printf("I am child,pid = %d\n",getpid());
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值