【问题标题】:Why doesn't my daemon terminate when I log out?为什么当我注销时我的守护进程没有终止?
【发布时间】:2013-02-20 10:10:13
【问题描述】:

我正在阅读有关 Linux 进程组和会话的信息。来自this site我看到了:

当用户退出系统时,内核需要终止用户运行的所有进程...为了简化此任务,进程被组织成会话集。会话的 ID 与通过 setsid() 系统调用创建会话的进程的 pid 相同。该进程称为该会话组的会话负责人。然后,该进程的所有后代都是该会话的成员,除非他们专门从该会话中删除自己。 setsid() 函数不接受任何参数并返回新的会话 ID。

文章没有说明操作系统决定终止用户会话的时间。我最初的假设是,当有人登录 TTY 时,TTY 是会话领导者,并且在该会话中调用的所有进程都属于它,除非他们调用 setsid()。然而,正如最简单的例子所证实的那样,这显然是错误的。考虑一下这个“守护进程”...(我知道它不是真正的守护进程,但它确实分叉)...

#include 
#include 
#include 
#include 

int main(void) {

  pid_t pid = fork();

  if(pid < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
  }

  if(pid == 0) {
    FILE * heartbeat_file = fopen("daemon.out", "w");
    int hb = 0;
    while(1) {
      fprintf(heartbeat_file, "%d\n", hb);
      fflush(heartbeat_file);
      hb++;
      sleep(1);
    }
  } 
  exit(EXIT_SUCCESS);
}

从代码中,我们看到子进程不断地写入文件,而父进程退出。请注意,我从不打电话给setsid()

如果我登录,运行守护程序,然后注销,然后登录,守护程序仍在运行!我可以删除对fork() 的调用,并且正如预期的那样,当我注销时进程终止。谁能解释为什么我注销时 fork 导致应用程序不退出?

【问题讨论】:

    标签: linux posix fork daemon setsid


    【解决方案1】:

    当你在让父进程退出的同时分叉时,你创建了一个孤儿进程 (http://en.wikipedia.org/wiki/Orphan_process)。 这些孤儿被重新设置为 init 进程。我会根据您观察到的情况假设重新育儿会修改会话的 ID。

    测试这个假设的一个直接方法是让父母等待孩子(对不起,我现在不在我的 linux 机器上,不能这样做)。

    【讨论】:

      猜你喜欢
      • 2018-07-28
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2022-08-08
      • 2020-01-20
      • 1970-01-01
      相关资源
      最近更新 更多