【问题标题】:pipe, fork, and non-blocking IPC管道、分叉和​​非阻塞 IPC
【发布时间】:2011-07-08 05:57:36
【问题描述】:

所以我试图在 fork() 之后在子进程中运行系统命令(或 exec 或其他),并将一些输入推送给它,然后获取它的输出。在fork()之后是这样的,pc和cp是父子管道和子父管道。

  case 0:
        /* Child. */
        close(STDOUT_FILENO); /* Close current stdout. */
        dup2(cp[1], STDOUT_FILENO);

        close(STDIN_FILENO);
        dup2(pc[0], STDIN_FILENO);

        close( pc[1]);
        close( cp[0]);
        execlp("cat", "cat", NULL);
        exit(1);
  default:
        /* Parent. */
        /* Close what we don't need. */
        printf("Input to child:\n");

        string theinput("Hey there baby");
        write(pc[1], theinput.c_str(), theinput.size());
        close(pc[1]);

        cout << "The input : " << theinput << endl;


        printf("\nOutput from child:\n");
        close(cp[1]);
        while( read(cp[0], &ch, 1) == 1)
        {
           write(1, &ch, 1);
           outcount++;
        }

        exit(0);

现在,它似乎工作得很好(如果你想要代码:http://pastebin.com/Fh7GrxYm),但是当我在 irc 上的 #posix 上讲话时,他们疯了,关于这可能如何阻止,以及它如何“取决于关于内核的感受”。

有一篇关于同一件事的 msdn 博客文章:http://blogs.msdn.com/b/oldnewthing/archive/2011/07/07/10183884.aspx

如何防止阻塞(如果有的话)等?

【问题讨论】:

    标签: posix fork pipe interprocess


    【解决方案1】:

    在你的情况下,当父进程到达这一行时,可能会发生死锁:

    write(pc[1], theinput.c_str(), theinput.size());
    

    如果“输入”是很多数据,那么父进程可能会填满pc 管道。子进程(此处为cat)可能会读取其中的一部分但不是全部。 cat 他们会将其回馈给您。但同样,如果它有很多数据,它可能会填满cp 管道并阻塞,直到有人从该管道中读取数据。这永远不会发生,因为父进程被阻塞等待pc 管道耗尽,并且永远不会到达消耗cp 管道内容的代码。死锁。

    就像你的 IRC 伙伴说的那样,这是否发生取决于很多事情,例如所涉及的数据量、管道在阻塞之前可以容纳的数据量(依赖于内核的参数)、 stdio 或其他由父进程或子进程执行的缓冲等...

    您的选择是:

    1. 使用两个进程来控制外部命令:一个向其提供数据,另一个将结果读回。为此,您必须两次fork()。这看起来很像一个 shell 管道。按照惯例,最终数据源是孙进程,过滤器是中间父进程,最终数据接收器是授权父进程。

    2. 使用两个线程来控制外部命令。与上一个选项类似。

    3. 使用非阻塞 I/O 来控制外部命令。使用fcntl() 将两个文件描述符设置为非阻塞模式,并使用poll()select() 设置一个事件循环以等待任一文件描述符准备好。当任一文件描述符准备就绪时,请准备好让write() 仅完成部分操作,并让read() 不会一次读取所有内容。

    4. 使用现有的事件循环,如glib's,将管道设置为IO Channels,并设置watch them 以了解何时读取或写入数据。与上一个选项类似,但使用现有框架,因此您可以与现有应用程序事件循环集成。

    顺便说一句:您的 exit(1) 应该是 _exit(1) 以防止 C 库在短暂的子进程中不恰当地调用退出时间挂钩。

    【讨论】:

      猜你喜欢
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 2016-08-09
      • 2010-12-16
      相关资源
      最近更新 更多