孤儿进程、僵尸进程和守护进程

孤儿进程、僵尸进程和守护进程

孤儿进程

定义

当fork出来的子进程的父进程结束,但是子进程并未结束时,子进程会成为孤儿进程;孤儿进程会被init进程接管,init进程负责孤儿进程的释放。在Ubuntu18.04系统中,孤儿进程被“/lib/systemd/systemd --user”进程领养。

代码例子

#include <iostream>
#include <unistd.h>

int main(void)
{
    pid_t pid = fork();

    if (pid == 0) {
        while (true) {
            std::cout << "I'm child process, parent process id is " << getppid() << std::endl;
            sleep(1);
        }
    } else if(pid > 0) {
        sleep(9);
        std::cout << "I'm parent process,id is " << getpid() << std::endl;
    }
    return 0;
}

僵尸进程

定义

进程终止,父进程尚未回收,子进程资源残留与内核,变成僵尸进程。僵尸进程无法用kill命令杀掉。只能杀掉其父进程,之后僵尸进程会被init进程领养。

僵尸进程的避免

  1. 父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起。
  2. 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后, 父进程会收到该信号,可以在handler中调用wait回收。
  3. 如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD,SIG_IGN) 通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收, 并不再给父进程发送信号。
  4. 还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一 个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收 还要自己做。

代码例子

#include <iostream>
#include <unistd.h>

int main(void)
{
    pid_t pid = fork();

    if (pid == 0) {
        std::cout << "child process start, parent process id is " << getppid() << std::endl;
        sleep(9);
        std::cout << "child process quit, parent process id is " << getppid() << std::endl;
    } else if(pid > 0) {
        while (true) {
            sleep(1);
            std::cout << "I'm parent process,id is " << getpid() << std::endl;
        }
    }
    return 0;
}

守护进程

定义

Daemon独立于控制终端,周期性的执行某种任务,或等待处理某些发生的事件,一般采用以d结尾的名字。

代码例子

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int main(void)
{
    pid_t pid = fork();
    if (pid == 0) {
        exit(0);
    }

    //创建新会话
    pid = setsid();
    if (pid == -1) {
        std::cout << "setsid error" << std::endl;
        return -1;
    }

    //改变工作目录,一般改为根目录
    int ret = chdir("/home/yzz/");
    if (ret == -1) {
        std::cout << "chdir error" << std::endl;
        return -1;
    }

    //设置umask
    umask(0022);

    //关闭文件描述符0
    close(STDIN_FILENO);
    int fd = open("dev/null", O_RDWR);
    if (fd == -1) {
        std::cout << "open error" << std::endl;
        return -1;
    }
    //重定向STDOUT,STDERR
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);

    //模拟Daemon业务
    while (true) {}
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值