2013-03-05 43 views
1

我在阅读有关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导致应用程序在退出时不会退出?

回答

1

当您让父项退出时分叉时,将创建一个孤立进程(http://en.wikipedia.org/wiki/Orphan_process)。 此类孤儿重新注册到init过程。我会从你所观察到的情况出发,重新修改会话的ID。

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

相关问题