2011-04-15 81 views
3

在我的程序中,我將子進程的輸出重定向到管道,並在父進程中獲取此結果並執行某些操作(這不重要)。但是,當我使用​​命令時,我的程序不起作用,並且在尾部運行期間沒有收到任何數據,只有尾部完成(或終止)後才能獲取此數據。爲什麼無法從tail -f獲取數據?

起初我以爲問題是tail -f不刷新,這就是爲什麼我沒有收到數據,但是當我試圖將tail -f的輸出重定向到某個文件時,即使尾部是沒做完。

//the code of creating child and redirecting data (important part) 
//only core is here so please don't tell me that maybe pipe() or fork() is failed 

pid_t pid; 
int outpipe[2]; //pipe for reading from stdout 
int errpipe[2]; //pipe for reading from stderr 

// Createing pipes for childs stdout and stderr streams 
pipe(outpipe); 
pipe(errpipe); 
pid = fork(); 
if(pid == 0) 
{ 
    // This is the child process. Closing read end of pipes and duplicating stdout and stderr streams 
    close(outpipe[0]); 
    dup2(outpipe[1], STDOUT_FILENO); 
    close(errpipe[0]); 
    dup2(errpipe[1], STDERR_FILENO); 

    if(execvp(argv[0], (char * const *)argv) == -1) 
    { 
     fprintf(stderr, "Failed to execute command %s: %s", argv[0], strerror(errno)); 
     _exit(EXIT_FAILURE); 
    } 

    _exit(EXIT_SUCCESS); 
} 
else if (pid != -1) 
{ 
    // This is the parent process, Closing write end of pipes and opening fds as FILE 
    close(outpipe[1]); 
    *child_stdout_stream=fdopen(outpipe[0], "rt"); 
    close(errpipe[1]); 
    *child_stderr_stream=fdopen(errpipe[0], "rt"); 
    *child_pid=pid; 
} 

然後,我從其中作爲參數傳遞給函數以上的部分是由什麼child_stderr_streamchild_stdout_stream閱讀。 對於閱讀,我使用select()在從其中一個流讀取之前不阻止程序。


添加的選擇部分和閱讀

int select_and_read(FILE **files, bool *is_eof, char *chars, int *mask, int nfiles, int timeout, pid_t child_pid) 
{ 
    int max_fd_plus_1 = 0; 
    fd_set rfds; 
    struct timeval tv; 

    FD_ZERO(&rfds); 

    for(int i = 0; i < nfiles; ++i) 
    { 
     if(is_eof[i]==false) 
     { 
      FD_SET(fileno(files[i]), &rfds); 
      max_fd_plus_1 = (max_fd_plus_1 > fileno(files[i])) ? max_fd_plus_1 : fileno(files[i]); 
     } 
    } 
    ++max_fd_plus_1; 

    tv.tv_sec = timeout/1000; 
    tv.tv_usec = (timeout % 1000) * 1000; 

    int retval = select(max_fd_plus_1, &rfds, NULL, NULL, &tv); 
    if(retval > 0) 
    { 
     *mask = 0; 
     for(int i = 0; i < nfiles; ++i) 
     { 
      if(is_eof[i]==false) 
      { 
       if(FD_ISSET(fileno(files[i]), &rfds)) 
       { 
        *mask |= 1 << i; 
        chars[i] = fgetc(files[i]); 
       } 
      } 
     } 
    } 
    else 
    { 
     kill(child_pid, SIGKILL); 
    } 
    return retval; 
} 
+0

問題可能在select()中。添加一些調試以查看當您連接到標準輸出時FD是否準備就緒。也許你是選擇()在標準輸出? – FoneyOp 2011-04-15 15:35:36

+0

是select()不告訴我可以從流中讀取。它掛起,但爲什麼?我怎麼解決這個問題? – 2011-04-15 15:37:08

回答

1

這個奇怪的問題都已經解決了非常奇怪。我剛纔設置文件緩存到0這樣:

else if (pid != -1) 
{ 
    // This is the parent process, Closing write end of pipes and opening fds as FILE 
    close(outpipe[1]); 
    *child_stdout_stream=fdopen(outpipe[0], "rt"); 
setbuf(*child_stdout_stream, NULL); 
    close(errpipe[1]); 
    *child_stderr_stream=fdopen(errpipe[0], "rt"); 
setbuf(*child_stderr_stream, NULL); 
    *child_pid=pid; 
} 

這是很奇怪的,這會有所幫助,但在任何情況下,我的程序現在運作良好。