Linux c/c++进程之僵尸进程和守护进程

目录

 

1. 僵尸进程

1.1 僵尸进程的定义:

1.2 僵尸进程的解决办法

2.守护进程

2.1  守护进程概念

2.2 守护进程的查看方法

2.3 守护进程的创建 

2.4 创建守护进程编程模型

2.5 进程的组织形式

2.6 守护进程的关闭

2.7 终端标准输入输出设备


1. 僵尸进程

1.1 僵尸进程的定义:

       父进程创建了子进程,而子进程先于父进程结束,子进程的资源没有被释放,就会变成僵尸进程,持续占用系统资源

1.2 僵尸进程的解决办法

       子进程在结束之前会向父进程发送SIGCHLD信号,父进程接收到信号之后,先回收子进程资源,然后父进程自己再结束

       想要防止僵尸进程的情况出现,可以在父进程中写一个wait函数(或者waitpid函数)等待子进程发送的SIGCHLD信号

无wait()函数的情况:

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

int main(){
	if(fork()){
		printf("子进程被创建!\n");
	}else{
		for(int i = 0;i<5;i++){
			printf("子进程执行:%d\n",i+1);
			sleep(1);
		}
	}
	printf("父进程结束!\n\n");
	return 0;
}

 运行结果:

     从上面的输出结果可以看出,在没有wait()函数的情况下,父进程并不会等待子进程结束之后再执行"父进程结束!"这句话,如果在此时父进程在子进程未结束前被强制结束,那么就会造成僵尸进程的情况出现

 有wait()函数的情况:

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

int main(){
	if(fork()){
		printf("子进程被创建!\n");
		wait(0);
	}else{
		for(int i = 0;i<5;i++){
			printf("子进程执行:%d\n",i+1);
			sleep(1);
		}
	}
	printf("父进程结束!\n\n");
	return 0;
}

 运行结果:

 

       当存在wait()函数时,父进程会等待子进程发送的SIGCHLD信号,当父进程接收到信号之后,先回收子进程资源,父进程再结束

2.守护进程

2.1  守护进程概念

独立记录其它进程的情况,记录操作系统日志等

2.2 守护进程的查看方法

 ps  -axj

TPGID为 -1 的是守护进程

  

2.3 守护进程的创建 

 2.3.1 守护进程的功能实现和其它进程一样

 2.3.2 将一个进程变为守护进程的步骤

  • 干掉其父进程
  • 摆脱终端控制(关闭0 1 2 文件描述符并重定向当前进程的io操作到 /dev/NULL (黑洞设备))
  • 摆脱原有会话,进程组的控制从而创建新的会话

2.4 创建守护进程编程模型

 2.4.1 创建守护进程方式一

  1.  创建新会话                setsid()函数
  2.  改变当前工作目录      chdir()函数
  3.  重设当前文件权限      umask()函数
  4.  关闭文件                     close()函数

 2.4.2 创建守护进程方式二

  1.   重设文件权限                          umask()函数
  2.   创建子进程                              fork()函数
  3.   结束父进程                              
  4.   创建新会话                              setsid()
  5.   防止子进程成为僵尸进程         signal()函数忽略掉SIGCHLD  SIGHUP信号
  6.   改变当前工作目录                     chdir()函数
  7.   重定向文件描述符号                 open()函数    dup2()函数
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(){
	// 1. 重设文件权限
	umask(0);
	// 2. 创建子进程
	int ret = fork();
	if(ret < 0) printf("创建进程失败:%m"),exit(-1);
	if(ret > 0) printf("父进程结束:%m\n"),exit(0); 	// 3. 让父进程结束
	if(0 == ret){
		printf("pid:%d\n",getpid());
		// 4. 创建新会话
		setsid();
		// 5. 防止子进程成为僵尸进程   忽略掉SIGCHLD SIGHUP信号
		signal(SIGCHLD,SIG_IGN);
		signal(SIGHUP,SIG_IGN);
		// 6. 改变当前工作目录
		chdir("/");
		// 7. 重定向文件描述符号
		int fd = open("/dev/NULL",O_RDWR);
		dup2(fd,0);
		dup2(fd,1);
	}
	
	while(1){
		//做事情(模拟守护进程工作)
		sleep(1);
	}

	return 0;
}

结果: 

 关闭守护进程:

 由此可知上方创建的pid为3469的守护进程已经被关闭

2.5 进程的组织形式

 多个进程组成一个进程组

 多个进程组组成一个会话

 注: 进程组的组长 session进程

 2.6 守护进程的关闭

 直接使用kill 2 pid 将指定进程干掉即可

 2.7 终端标准输入输出设备

  •  0    标准输入设备
  •  1    标准输出设备
  •  2    标准错误输出设备
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

石小浪♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值