【问题标题】:Fork, exec -> man. Doesn't work correctly叉子,执行 -> 人。无法正常工作
【发布时间】:2010-12-12 15:05:12
【问题描述】:

在这种情况下,我写了一个简单的 prog:

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

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

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

【问题讨论】:

    标签: unix process


    【解决方案1】:

    通过在子进程运行时从父进程退出,您只是守护了子进程。守护进程及其分支没有控制终端,这是寻呼机运行的必要条件(我相信pager -sless(1),但请检查:man pager)。

    另一方面,即使对于守护进程来说,仅仅写入 STDOUT 也不是犯罪,尽管不能保证任何人都会在那里阅读输出。

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

    【讨论】:

    • 非常感谢您的链接。很棒的书,我一直在寻找这样的书=)至于我的问题:在我的情况下,shell 是会话负责人。当我运行我的 prog 时,shell 创建新组并相应地设置控制终端,即我的 prog 有控制终端。比它分叉和死亡。分叉的进程不会更改其组,因此即使在父进程死亡后它也必须具有控制终端。因此它不能成为一个守护进程。我哪里不对?
    • 嗯,我已经尝试从您的示例中运行 /bin/ps -o pid,ppid,pgid,sid,tty,state,args - 是的,它确实保留了控制终端等.所以我的回答基本上是错误的。
    • 尝试执行 "/usr/bin/strace", -f, "/usr/bin/man" ... 并使用 2>file 运行程序,你会看到(文件内)为什么寻呼机失败。
    • Strace'ing man 没有得到任何东西——男人的工作就像它必须做的那样。
    • 我做了以下操作:strace -f ./a.out > temp.txt。在 temp.txt 中,我找到了常用的 ps 手册页。我真的不能理解这一点。(
    【解决方案2】:

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

    【讨论】:

    • 问题在于理解它为什么不起作用,而不仅仅是解决它。
    【解决方案3】:

    所以。一项小研究表明,shell 在启动我的进程后,通过setpgid() 将控制终端设置为它(我的进程)。当它死时,shell 再次调用setpgid(),尽管我的过程中有fork 的所有孩子。所以它们已经是守护进程。正如我发现的那样,守护进程也可以执行一些输出例程,但它们并不一定会成功。可能是,可能不是。这就是为什么孩子在父母去世后仍然可以输出(例如,如果我分叉一个简单的 piriodical writong hello world 程序)。男人明白他的输出会被弄错并开始恐慌。我就是这么看的。

    至于strace,很简单:在我的程序的所有生命周期中,strace 仍然存在,所以输出没有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 2020-03-29
      相关资源
      最近更新 更多