Unix中的C语言:fork,waitpid和pipes

时间:2016-06-18 09:12:52

标签: c unix pipe fork waitpid

我的问题是如何控制关于管道的流程执行,特别是using System; using System.Threading; using System.Threading.Tasks; namespace Demo { class Program { void run() { Task.Factory.StartNew(resetFlagAfter1s); var waiter = Task.Factory.StartNew(waitForFlag); waiter.Wait(); Console.WriteLine("Done"); } void resetFlagAfter1s() { Thread.Sleep(1000); flag = false; } void waitForFlag() { int x = 0; while (flag) { ++x; // Uncommenting this line make this thread see the changed value of flag. // Console.WriteLine("Spinning"); } } // Uncommenting "volatile" makes waitForFlag() see the changed value of flag. /*volatile*/ bool flag = true; static void Main() { new Program().run(); } } } / wait函数的实现。

当我为以下命令waitpid创建管道时,我执行以下操作:

  • 我创建了一个管道,分叉创建一个孩子的过程
  • 对于孩子,我为stdin调用dup2,执行ls | head -3命令,关闭子项中管道的输出端
  • 对于父级,我为stdout调用dup2,执行head -3命令,关闭父级管道的输入端

我的问题:based on this discussion,我确实需要等待孩子完成执行,即执行ls。但是我如何/在哪里实现head -3函数的方式不会与waitpid命令冲突?

基于this great text,描述如下:

  

如果父母想要从孩子那里接收数据,它应该关闭fd1,孩子应该关闭fd0。如果父母想要向孩子发送数据,它应该关闭fd0,孩子应该关闭fd1。由于描述符在父级和子级之间共享,因此我们应始终确保关闭我们不关心的管道末尾。从技术角度来说,如果未明确关闭管道的不必要的末端,则永远不会返回EOF。

因此,在执行之前,孩子必须等待父母完成管道。

我还看过一些示例,其中两个叉子用于管道的一个过程。是否可以避免僵尸进程,就像我的APUE ch.8副本中的描述一样?

考虑以下代码实现:

close[]

我必须承认,我在StackExchange上查看了很多类似的问题。然而,几乎所有这些都具有特定的内容。我正在寻找的是原理的解释和功能的组合。谢谢你的时间!

1 个答案:

答案 0 :(得分:0)

你不能都想等孩子和高管。所以你需要有两个孩子。有两种常见的方法可以做到这一点,或者有一个父进程创建两个直接子进程,然后可以/必须等待两者;或者让一个孩子自己创建第二个孩子,这样父母只需等待一个过程终止。

选项1 (继承管道)

pipe(pi);
pid1 = fork();
if (pid1==0) { // child1
  // make redirections
  exec("head"...);
}
pid2 = fork();
if (pid2==0) { // child2
  // make redirections
  exec("ls"...);
}
// parent process
// close unuseful pipe
waitpid(pid1...);
waitpid(pid2...);

选项2 (管道只对相关进程可见)

pid1 = fork();
if (pid1==0) { // child
  pipe(pi);
  pid2 = fork();
  if (pid2==0) { // gran child
    // make redirections
    exec("ls"...);
  }
  // make redirections
  exec("head"...);
}
// parent process
waitpid(pid1...);