【问题标题】:Waitpid blocks foreverWaitpid 永远阻塞
【发布时间】:2016-04-07 19:35:35
【问题描述】:

我对waitpid函数有点困惑:

int main(int argc, char** argv) {
    if (pid_t pid = fork()) {
        setpgid(pid, pid);
        waitpid(pid, NULL, 0);
    } else {
        setpgid(0, 0);
        char *args[] = {"man", "2", "pipe", NULL};
        execvp(args[0], args);
    }

    return 0;
}

在这个例子中,程序只是阻塞,什么都没有。同样的故事也适用于等待您按“q”的每个程序。另一方面,如果我将 man 替换为 say "ls" - 一切正常:它会打印目录的内容。

char *args[] = {"ls", NULL};

那么男人有什么特别之处呢?

编辑:我忘了说我需要这个过程才能成为团队的领导者。如果我删除 setpgid() 一切也都可以:

int main(int argc, char** argv) {
    if (pid_t pid = fork()) {
        waitpid(pid, NULL, 0);
    } else {
        char *args[] = {"man", "2", "pipe", NULL};
        execvp(args[0], args);
    }

    return 0;
}

【问题讨论】:

  • 你在什么操作系统上运行这个?
  • 我使用的是 Ubuntu 14.04
  • 您正在创建自己的外壳吗?我不知道进程组的确切用途,但在setpgid() 手册页中,shell 似乎使用它们来重新组合同一作业的进程,所以除非你是,否则尝试覆盖它可能是个坏主意写一个shell。
  • 是的,我正在用管道编写 shell。我需要进程组向管道中的所有程序发送信号。
  • 你能用 C 编译器编译它吗? (if 条件中的声明)

标签: c linux posix wait waitpid


【解决方案1】:

您将子进程置于其自己的进程组中。会话的控制终端在任何给定时间都只有一个前台进程组,您无需将子进程组置于前台。因此,它不接收键盘输入,其标准输出也不显示在终端上。

因为您在子进程中执行的命令等待键盘输入,而该命令在后台时永远不会出现,该命令永远不会退出,并且waitpid() 永远不会收集它。

除非您有特定原因将子进程置于不同的进程组中,否则您可能不应该这样做。

【讨论】:

  • 非常感谢!
  • 如果您确实需要将子进程放入自己的进程组,您应该使用tcsetpgrp 来控制终端的前台进程组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 2013-09-24
相关资源
最近更新 更多