1

子スクリプトを生成するプログラムがあります。子スクリプトは、STDOUT および STDERR に 1/2 の時間で入力を単純に再発行します。残りの半分の時間は、静かに消費します。私が得ているのは、子への書き込みからの結果のタイミングのずれです。

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

行番号 1 は、同じ Line1 読み取りによって読み取られているはずです。同様に、回線番号 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: %s\n", 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 %d\n", 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 leftovers\n");
    while (fgets(line, 80, istream)) {
      fprintf (stdout, "endLine: %s", line);
      fflush (stdout);
    }

    close (p2child[1]);
    close (c2parent[0]);

    waitpid (pid, NULL, 0);
  }
  fprintf (stderr, "Exiting\n");
}
4

1 に答える 1

0

fgets() を呼び出すと、ストリームから行入力を読み取りますが、stdio 自体がさらに読み取り、それをバッファリングした可能性があります。これはあなたの問題です。select() は予想よりも早く 0 を返しています。これは、前の fgets() 呼び出しによって stdio が残りのすべての入力を吸収したためです。試しに交換

                fgets(line, 80, istream);

選択ループで

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

残りの入力がなく、読み取りと書き込みがロックステップに入るはずです。

于 2012-01-28T08:22:07.420 に答える