2010-12-12 72 views
0

工作,在这种情况下,我写了一个简单PROG:Fork,exec - > man。不能正确

int main() 
{ 
    pid_t chpid; 
    chpid=fork(); 
    if(chpid==0) // child 
    { 
    sleep(2); 
    execlp("/usr/bin/man","/usr/bin/man","ps",NULL); 
    printf("still alive\n"); 
    } 
    else 
    { 
    printf("parent goes down\n"); 
    } 
    return 0; 

} 

在运行父母去世&在2秒钟内我得到:/usr/bin/man: command exited with status 1: pager -s

为什么会这样运行的?绝对的问题是父母的死亡,如果我添加(1)在父母的代码中一切都很好。

我写了一个测试编程,每个时间段都将一些字符串写入标准输出。有用。看起来很奇怪。

回答

0

所以。一个小小的研究表明,外壳,开始我的过程,设置控制终端(我的过程)setpgid()。当它死亡时,shell会再次调用setpgid(),尽管所有的孩子都是我的proc所编辑的fork。所以他们已经是守护神了。正如我发现的,守护进程也可以执行一些输出例程,但是它们并不一定能够成功。也许是,也许不是。这就是为什么孩子在父母去世后仍然可以做出输出的原因(例如,如果我掏出一个简单的piriodical writeong hello world program)。而且男人明白,他的产量会随之下降,并开始恐慌。这是我看到它的方式。

至于strace,这很简单:strace在我的程序的所有生命周期中都还活着,所以对于那个输出没有问题。

0

使用wait(3p)等待孩子死亡。

+0

问题是为什么它不起作用,不仅仅是为了解决它。 – DimG 2010-12-12 15:11:39

1

通过在孩子跑步时从家长处退出,您刚刚将孩子奉献给了孩子。它的守护进程和分叉没有控制终端,这是寻呼机运行的要求(我相信pager -sless(1),但检查它:man pager)。另一方面,即使对于一个守护进程,直接写入STDOUT也不算犯罪,尽管不能保证有人会在那里读取输出。

有关更好的解释,请参阅Richard Stevens关于进程组,会话和控制终端的“Advanced Programming in the UNIX Environment”。

+0

真的非常感谢您的链接。神奇的书,我一直在寻找就像那样=)关于我的问题:在我的情况下,壳是会议的领导者。当我运行我的编程时,shell会创建新的组并相应地设置控制终端,即我的编程控制终端。比它叉和死。分叉过程不会改变其组,因此它必须有控制终端,即使在父母死亡之后。因此它不能成为守护进程。我不对? – DimG 2010-12-13 13:58:06

+0

嗯,我已经试过运行/ bin/ps -o pid,ppid,pgid,sid,tty,state,你的示例中的参数 - 是的,它保留了控制终端等。所以我的回答基本上是错误的。 – Dallaylaen 2010-12-13 15:34:00

+0

尝试执行“/ usr/bin/strace”,-f,“/ usr/bin/man”...并使用2>文件运行该程序,您会看到(文件内)为什么寻呼机失败。 – Dallaylaen 2010-12-13 16:40:54