2012-01-24 8 views
1

私は子スクリプトを生成するプログラムを持っています。子スクリプトは、時間の1/2の入力をSTDOUTとSTDERRに単純に戻します。残りの半分は静かに消費します。行番号1は、同じライン1を介して読み出されている必要がありますC exec/pipe/select program - 子からの入力がありません

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

が読み:私は何を取得していますと、子供への書き込みからの結果の誤タイミングです。同様に、行番号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プログラム:あなたはfgetsの()を呼び出すと

#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"); 
} 
+0

追加のメモ。私は、子プログラムが返す行が何行であっても、最初の行だけが送信された後にピックアップされることを発見しました。残りのすべての行は、後で2回反復され、その反復から1行だけ取り出されます。 –

答えて

0

は、あなたが自分自身STDIOラインストリームからの入力が、を読みますもっと読むことができ、それをバッファしているかもしれません。;これがあなたの問題です。以前のfgets()呼び出しがstdioに残りのすべての入力を吸収させたため、select()は期待したよりも早く0を返しています。テストとして、

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

で選択ループに

   fgets(line, 80, istream); 

を交換し、あなたが読み、無残り物入力してロックステップに秋を書き込み表示されるはずです。

関連する問題