为不阻塞且可以重用的子进程创建非阻塞管道

Creating non blocking pipes to child that does not block and can be reused

我正在尝试使用管道创建进程间通信总线。 我可以向客户端发送消息,也可以在客户端接收消息。

我还尝试创建另一个方向相反的管道,child-> parent。

但是我需要这种通信是非阻塞的,我想在两个方向上发送消息,中间有一些未定义的时间间隔。

看来我不能发送超过一条消息,我认为这是由于 fclose(); 关闭了流,但是如果我删除关闭,程序将停止工作...

如何使此代码通过管道实现非阻塞双向父 -> 子通信?

稍后我想使用 exec() 连接一个子二进制文件,并将这个二进制文件的标准输入、标准输出连接到我的父级,这样我就可以将消息传递给子级的标准输入并通过 "childParent"描述符。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define READ_SIDE 0
#define WRITE_SIDE 1

  /* Read characters from the pipe and echo them to stdout. */


  void
  read_from_pipe (int file)
  {
    FILE *stream;
    int c;
    stream = fdopen (file, "r");
    while ((c = fgetc (stream)) != EOF)
      putchar (c);
    fclose (stream);
  }

  /* Write some random text to the pipe. */

  void
write_to_pipe (int file, char * message)
  {
    FILE *stream;
    stream = fdopen (file, "w");
    fprintf (stream, message);
    //fprintf (stream, "goodbye, world!\n");

    //Dont forget to close
    fclose (stream);
  }

void end(){
  //kill process and close pipes

}



  int
  main (void)
  {
    pid_t pid;
    int parentToChild[2];
    int childToParent[2];

    /* Create the pipes. */
    if (pipe (parentToChild))
    {
      fprintf (stderr, "Pipe failed.\n");
      return EXIT_FAILURE;
    }

    if (pipe (childToParent))
    {
      fprintf (stderr, "Pipe failed.\n");
      return EXIT_FAILURE;
    }


    /* Create the child process. */
    pid = fork ();
    if (pid == (pid_t) 0)
    {
      /* This is the child process.
       Close other end first. */
      close(childToParent[READ_SIDE]);
      close (parentToChild[WRITE_SIDE]);
      read_from_pipe (parentToChild[READ_SIDE]);
      write_to_pipe(childToParent[WRITE_SIDE], "Child sent message to parent");
      return EXIT_SUCCESS;
    }
    else if (pid < (pid_t) 0)
    {
      /* The fork failed. */
      fprintf (stderr, "Fork failed.\n");
      return EXIT_FAILURE;
    }
    else
    {
      /* This is the parent process.
       Close other end first. */
      close(childToParent[WRITE_SIDE]);
      close (parentToChild[READ_SIDE]);
      write_to_pipe (parentToChild[WRITE_SIDE],"Parent sent message to child");
      read_from_pipe(childToParent[READ_SIDE]);
      //Send more messages...

      return EXIT_SUCCESS;
    }
  }

更新 似乎有时通信只以一种方式发生,这取决于我猜哪个进程首先到达 read/write。

有几个问题需要考虑。首先,管道有一个有限的 最大长度(4096 在遥远的过去很常见);任何写一个 管道中的数据多于将阻塞的数据,任何读取也是如此 来自空管。这些是管道工作方式的基础,所以 当你谈到非阻塞时,你必须考虑到它们 (或者使用异步IO)。

其次,如果你真的需要在这个层面上控制事情,你可能 想考虑使用 Posix 级 IO,而不是流。如果你这样做 使用流(iostream 或 FILE*),那么你必须考虑 考虑他们使用的缓冲。特别是,当您想确定 数据输出到管道,需要flush (fflush on FILE*)。关于发送多个消息,以及 如果没有 fclose,代码将无法工作,将 fclose 替换为 fflush 应该是解决此问题所需的全部内容。

当我在做的时候:你使用 fprintf 输出是非常 危险的。如果您收到来自外部来源的消息,并且 (可能)不知道它包含什么,你应该使用 fputs 来输出 它,或者可能是 fprintf( fd, "%s\n", message ) 之类的东西(如果你 想追加一个新行)。正如您所做的那样,如果消息包含 a '%',会发生奇怪的事情。更一般地说,你应该更喜欢 更安全的 iostream,但对于像这样简单的事情,它不会 很重要。对于你实际做的事情,Posix 级 IO 是 可能恰到好处,或者更合适。 Posix级IO,你 没有得到任何格式或缓冲:但是因为你没有使用 格式化功能,以及缓冲它是您问题的一部分...