2011-04-15 85 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; 
} 

这是很奇怪的,这会有所帮助,但在任何情况下,我的程序现在运作良好。