blog:programming:linux_daemon_process

Linux daemon进程

什么是daemon进程

daemon进程是指长时间运行在后台的进程,也叫守护进程.

为什么会有daemon进程?

由于控制终端的原因(例如断开终端连接)会产生一些信号, 进程接受到这些信号的缺省动作是让进程退出.

daemon进程的特点:

没有控制终端,在后台运行

实现daemon进程的方法

    pid_t pid = fork();

    if( pid != 0 )
    {
        exit(0);//parent
    }

    //first children
    printf("first child: PID: %d\n", getpid());
    if(setsid() == -1)
    {
        printf("setsid failed\n");
        assert(0);
        exit(-1);
    }

    umask(0);

    pid = fork();

    if( pid != 0)
    {
        exit(0);
    }

    //second children
    printf("second child: PID: %d\n", getpid());
    chdir ("/");

    for (int i = 0; i < 3; i++)
    {
        close (i);
    }


    int stdfd = open ("/dev/null", O_RDWR);
    dup2(stdfd, STDOUT_FILENO);
    dup2(stdfd, STDERR_FILENO);
  • 第一次fork
    结束父进程,让init进程托管该进程,从而进入后台运行
    * setsid
    脱离控制终端,登录会话和进程组
    进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个 进程组。这些进程组共享一个控制终端。控制终端,登录会话和进程组是从父进程继承下来的.
    调用setsid后,The calling process将会成为: 1. the leader of the new session, the 2. the process goup leader of the new process group 3. has no controlling terminal 新的group ID 和 session ID就是the calling process的PID
    只有在calling process不是进程组长时,setsid才会创建一个新的session, 所以在setsid之前 必须要通过fork保证调用进程不是group leader
  • umask(0)

    重设文件掩码, 由于fork会从父进程继承文件创建掩码,所以将文件创建掩码清0
    * 第2次fork
    主要目的: 防止进程再次打开一个控制终端
    因为打开一个控制终端的前提条件是:“该进程必须是会话组长”, 再fork一次之后,进程ID就不 等于sid了,所以也就无法打开新的控制终端。
    * chdir(“/”)

    由于fork会继承当前的工作目录,当进程没有结束时,其工作目录是不能被卸载的, 为了防止这种情况,守护进程一般会将工作目录改变到根目录下.
    * 关闭文件描述符,并重定向标准输出、错误

    fork得到的进程会继承父进程打开的文件描述符,所以需要将他们关闭. 由于守护进程在后台运行,所以不应该在终端有任何输出信息,将标准输出和标准错误重定向到 /dev/null
    # 守护进程与&结尾的后台运行程序的区别

  • 守护进程已经完全脱离控制台,而后台进程并没有完全脱离终端. 在终端未关闭之前仍然会从终端 输出结果
  • 守护进程在关闭终端控制台时不会受影响,而后台程序将会停止.
  • 守护进程的会话组、工作目录、文件描述符都是独立的,而后台程序这些都没有改变
  • blog/programming/linux_daemon_process.txt
  • 最后更改: 2022/01/09 22:41
  • 127.0.0.1