Linux下各种特殊进程

1. 孤儿进程
1.1. 产生原因
  • 父进程结束,子进程还再运行,成为孤儿进程。
  • 孤儿进程会被init所领养,init进程会变为孤儿进程的父进程,为了能够释放子进程所占用的资源
  • 使用pstree命令可以查看。
  • 子进程再结束之后,可以释放用户空间,但是释放不了PCB,子进程的PCB必须由父进程进行释放,所以孤儿进程必须有父进程。
1.2. demo实现
#include <unistd.h>
#include <stdio.h>

int main(int argc,const char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
	    sleep(10);
		printf("==Child pid = %d,,ppid = %d",getpid(),getppid());
	}else
	{
		printf("==parent pid = %d",getpid());
	}
	return 0;
}
2. 僵尸进程
2.1. 产生原因

子进程结束了,但是父进程还在运行,即父进程没有及时对子进程资源进行回收,父进程不释放子进程的PCB,那么子进程就成了僵尸进程

2.2. demo
#include <unistd.h>
#include <stdio.h>

int main(int argc,const char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
		// 子进程正常退出
		sleep(1);
		printf("==Child pid = %d,,ppid = %d\n",getpid(),getppid());
	}else if(pid > 0)
	{
		while(1)
		{
			sleep(1);
		    printf("==parent pid = %d\n",getpid());
		}
		int status;
		// 释放子进程资源
		pid_t pr = wait(&status);
	}
	return 0;
}
2.3. 子进程如何查看
2.3.1 使用top查看僵尸进程

使用top命令查看时有一栏为S,如果状态为Z说明它就是僵尸进程。

Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie
2.3.2. 从ps中查看僵尸进程
ps -e -o stat,ppid,pid,cmd | egrep '^[Zz]'
2.4. 如何避免僵尸进程
  • 父进程调用waitpid()等函数来接收子进程退出状态
  • 附近出现结束,子进程则成为孤儿进程,由Init进程管理。
  • 两次fork,使用孙子进程执行当前主进程要执行的任务,这样子进程可以正常退出,孙子进程会变为孤儿进程继续执行
3. 守护进程
3.1 什么是守护进程

守护进程(Daemon Process),也就是通常说的Daemon进程,是Linux中后台服务进程,它是一个生存期较长的进程,通常独立于控制终端,并且周期性地执行某种任务或者等待处理某些发生的时间。
守护进程是个特殊的孤儿进程,这种进程脱离终端,避免进程被任何终端所产生的信息所大端,其在执行过程中的信息也不再任何终端上显示。

3.2. 创建守护进程步骤
  1. 调用umask(0),将文件模式创建屏蔽字改为0;
  2. 调用fork(),父进程退出。(原因:父进程终止可以让shell切换到前台继续等待用户输入命令。)
  3. 在子进程中调用setid(),为了使进程成为新会话的受进程,成为一个进程组的组长进程
  4. 调用chdir()修改当前工作目录
  5. 关闭相应的文件描述符。
3.3. demo
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

void create_daemon()
{
    // 1、 将文件模式创建屏蔽字设置为0
    umask(0);

    // 2、 调用fork 父进程退出
    pid_t pid = 0;
    if ((pid =  fork()) < 0)
    {
        perror("fork");
        exit(2);
    }
    if (pid > 0)
    { // father
        exit(3);
    }

    // 3、调用setsid 创建一个新的会话
    setsid();

    // 4、将当前工作目录改为更目录
    chdir("/");

    // 5、关闭不需要的文件描述符
    // NOFILE 为 <sys/param.h> 的宏定义  
    // NOFILE 为文件描述符最大个数,不同系统有不同限制  
    for(i=0; i < NOFILE; ++i)
    {  
        close(i);  
    } 

    // 6、忽略SIGCHLD 信号
    signal(SIGCHLD, SIG_IGN);
    
    // 守护进程逻辑
    while(1)
    {
        // Do something
    }
}

int main()
{
    create_daemon();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fantongl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值