【Linux】僵死进程和进程替换

一、僵死进程

1、了解进程的结构

(1)进程分为两部分:

  • PCB(进程控制块):控制一个进程,相当于一个struct。
    记录一个进程的相关执行过程和内存位置。
  • 进程实体:指定进程的操作。
    (2)创建进程:
    先申请一个PCB结点,再加载程序生成进程实体。
    (3)进程结束:
    先结束进程实体,再释放PCB。

2、什么是僵死进程?

(1)从结构上来说:进程实体已经被释放,但PCB结点并没有被释放。
因为在PCB中有一个退出码,用来查看进程退出原因,如果进程实体被释放,用户就要查看进程退出原因,所以如果要看退出码,PCB就不能被释放。
(2)从理论上来说: 一个进程执行结束,但是进程的PCB没有被系统释放。也就是父进程未结束,子进程结束,并且父进程没有获取子进程的退出码。
(3)代码实现僵死进程
在子进程和父进程10s的时间差内,子进程为僵死进程;当父进程执行结束后,子进程就变成了孤儿进程,被init所接管并处理。
孤儿进程:父进程结束,子进程未结束

int main()
{
	pid_t pid = fork() ;
	assert(pid != -1);
	if (pid == 0)
	{
		printf("child staring\n");
		sleep(10);
		printf("child over\n");
	}
	else
	{
		printf("father staring\n");
		sleep(20);
		printf("father over\n");
	}
	exit(0);
}

运行结果:

3、如何处理僵死进程?

(1)让父进程获取子进程的退出状态:pid_t wait(int *result);

  • result获取的是进程的退出码。
  • 返回值处理的是进程的pid
    (2)代码
int main()
{
	pid_t pid = fork() ;
	assert(pid != -1);
	if (pid == 0)
	{
		printf("child staring: %d\n",getpid());
		sleep(10);
		printf("child over\n");
	}
	else
	{
		pid_t id = wait(NULL);
		printf("id = %d\n",id);
		printf("father staring\n");
		sleep(20);
		printf("father over\n");
	}
	exit(0);
}

运行结果:

(3)但是使用wait有一个问题就是:
wait本身会阻塞,也就是等待事件发生,本身会挂起,直到有一个任意子进程退出。(然后才会执行父进程)

二、进程替换

1、为什么要用进程替换?

创建子进程后,子进程执行的还是父进程的指令,想让子进程执行另外的指令。

2、进程替换

(1)一个进程能够执行另一份程序
即,在fork之后,让子进程进行进程替换,父进程继续执行其指令,子进程执行另一份指令。
(2)注意:执行进程替换仅仅是替换进程所执行的指令集,并没有创建新的进程。

//test.c
int main(int argc,int argv[])
{
	printf("test:my pid = %d\n", getpid());
	int i = 0;
	for (; i < argc; ++i)
	{
		printf("argv[%d] = %s\n",i,argv[i]);
	}
	exit(0);
}

//main.c
int main()
{
	pid_t pid = fork();
	assert(pid != -1);
	if (pid == 0)
	{
		printf("child:my pid = %d\n", getpid());
		execl("./test", "./test", "nine", "percent", (char*)0);
		int i = 0;
		for (; i < 5; ++i)
		{
			printf("child\n");
			sleep(1);
		}
	}
	else
	{
		int i = 0;
		for (; i < 10; ++i)
		{
			printf("father\n");
			sleep(1);
		}
	}
	exit(0);
}

运行结果:

3、进程替换的方法

在子进程中调用exec函数来执行另一个程序,调用后,新程序完全替换子进程进行程序执行,exec并不创建新进程,所以进程的pid不会发生变化。
(1)库函数

  • int execl(const char *path, const char *argv, ,...(char* )0);
  • int execv(const char * path,char * const argv[]);
  • int execle(const char * path,const char * argv,char * const envp[]);
  • int execlp(const char * file,const char * argv,…(char* )0);
  • int execvp(const char * file,char * const argv[]);
  • int execve(const char * path,char * const argv[],char * const envp[]);
    (2)系统调用
  • int execve(const char * path,char * const argv[],char * const envp[]);
    其中,
    path:要执行的程序路径。
    file:要执行的程序名称。
    argv:命令行参数的矢量数组。
    envp:带有该参数的exec函数可以在调用时指定一个环境变量数组。
    argv:程序的第0个参数,即程序名自身。
    …:命令行参数列表。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值