我正在阅读有关 Linux 进程组和会话的信息。从这个网站我看到:
当用户退出系统时,内核需要终止用户运行的所有进程……为了简化这个任务,进程被组织成会话集。会话的 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 导致我注销时应用程序不退出?