C exec/pipe/select程序-缺少子级的输入



我有一个程序,它派生出一个子脚本。子脚本只是将任何输入的1/2时间重新发送回STDOUT和STDERR。另一半的时间,它悄悄地消耗掉了它。我得到的是给孩子写的结果的错误时机:

Line1: STDOUT Line number 1
Line3: STDERR Line number 1
Line3: STDOUT Line number 3
Getting leftovers
endLine: STDERR Line number 3

第1行应通过相同的第1行读取。类似地,第3行也应该被相同的第3行尝试拾取。

我试图解决的问题是,我希望能够给孩子写一行数据,检查是否有任何响应并重复。以下是测试程序:

子脚本:

#! /usr/bin/perl 
$| = 1;
select (STDERR);
$|=1;
my $i = 0;
open (F,">> e.out");
select F;
$|=1;
select (STDOUT);
while (<>) {
  chomp;
  print F "($_)n";
  if ($i++) {
    print "STDOUT $_n";
    print STDERR "STDERR $_n";
  }
  $i %= 2;
}
close F;

父C程序:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
main () {
  pid_t pid;
  int p2child[2];
  int c2parent[2];
  pipe (p2child);
  pipe (c2parent);
  if ((pid = fork()) < 0) {
    fprintf (stderr, "Fork error: %sn", strerror(errno));
/*
  Child Process
*/
  } else if (pid == 0) {
    close (p2child[1]);
    dup2 (p2child[0], STDIN_FILENO);
    close (c2parent[0]);
    dup2 (c2parent[1], STDOUT_FILENO);
    dup2 (c2parent[1], STDERR_FILENO);
    if (execlp ("./e", "./e", 0 )) {
perror("Exec failed");
    }
/*
  Parent Process
*/
  } else {
    FILE* istream;
    FILE* ostream;
    char line[80];
    fd_set set;
    struct timeval timeout;
    int ret;
    int counter;
    close (p2child[0]);
    close (c2parent[1]);
    ostream = fdopen (p2child[1], "w");
    istream = fdopen (c2parent[0], "r");
    for (counter = 0; counter < 5; counter++) {
      fprintf (ostream, "Line number %dn", counter);
      fflush (ostream);
      do {
        FD_ZERO(&set);
        FD_SET(c2parent[0], &set);
        timeout.tv_sec = 0;
        timeout.tv_usec = 500000;
        ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
        if (ret > 0) {
          fgets(line, 80, istream);
          fprintf (stdout, "Line%d: %s", counter, line);
          fflush (stdout);
        }
      } while (ret > 0);
    }
fprintf (stdout, "Getting leftoversn");
    while (fgets(line, 80, istream)) {
      fprintf (stdout, "endLine: %s", line);
      fflush (stdout);
    }
    close (p2child[1]);
    close (c2parent[0]);
    waitpid (pid, NULL, 0);
  }
  fprintf (stderr, "Exitingn");
}

当您调用fgets()时,您从流中读取了一行输入,但stdio本身可能读取了更多并缓冲了它;这是你的问题。select()比您预期的要早返回0,因为之前的fgets()调用导致stdio占用了所有剩余的输入。作为测试,更换

                fgets(line, 80, istream);

在的选择循环中

                char *p = line;
                do {
                    read(c2parent[0], p, 1);
                } while (*p++ != 'n');

您应该看到读取和写入是同步的,没有剩余的输入。

最新更新