2014-03-12 36 views
0

我正在进行一项任务,其中需要几个进程(父级和子级)进行通信。 父母向孩子们发送文件路径,他们必须在他们上运行linux file(/ usr/bin/file),将输出返回给父亲。未从管道获取所有行

现在我仍然试图让一个孩子上班,所以现在我假设有一个孩子。

我打算发送多个文件路径给每个孩子(一批文件),然后读取file的输出。

问题:

我使用循环write几个文件路径,但是当我read孩子的输出管道我没有得到所有我应该输出。

的代码:

#define Read   0 
#define Write   1 
#define ParentRead  read_pipe[0] 
#define ParentWrite  write_pipe[1] 
#define ChildRead  write_pipe[0] 
#define ChildWrite  read_pipe[1] 
#define PIPE_BUF_LEN 4096 

using namespace std; 
int main() 
{ 
    /** Pipe for reading for subprocess */ 
    int read_pipe[2]; 
    /** Pipe for writing to subprocess */ 
    int write_pipe[2]; 
    char buffer[PIPE_BUF_LEN] = ""; 
    if (pipe(read_pipe) == 0 && pipe(write_pipe) == 0) 
    { 
     pid_t pid = fork(); 
     if (pid == -1) 
     { 
      fprintf(stderr, "Fork failure"); 
      exit(EXIT_FAILURE); 
     } 
     else if (pid == 0) //Child process 
     { 
      close(ParentRead); 
      close(ParentWrite); 
      dup2 (ChildRead, STDIN_FILENO); /*redirect ChildRead to stdin*/ 
      dup2 (ChildWrite, STDOUT_FILENO); /*redirect stdout to ChildWrite*/ 
      char* paramArgs[]={"/usr/bin/file","-n","-f-",NULL}; 
      execv("/usr/bin/file",paramArgs); 
      exit(EXIT_FAILURE); 
     } 
     else { //Parent process 
      close(ChildRead); 
      close(ChildWrite); 

      for (int i=0; i < 3 ;i++) 
      { 
       /*write to processes which are ready for writing: */ 
       fd_set rfds; 
       int retval; 
       FD_ZERO(&rfds); 
       FD_SET(ParentWrite, &rfds); 
       retval = select(10, NULL, &rfds, NULL, NULL); 
       if (retval == -1) 
       { 
        perror("select()"); 
       } 
       else if (retval) 
       { 
        write(ParentWrite, "file1\nfile2\n", 12); 
       } 
       /*read from processes which are ready for reading*/ 
       FD_ZERO(&rfds); 
       FD_SET(ParentRead, &rfds); 
       retval = select(10, &rfds, NULL, NULL, NULL); 
       if (retval == -1) 
       { 
        perror("select()"); 
       } 
       else if (retval) 
       { 
        read(ParentRead, buffer, PIPE_BUF_LEN); 
        cout << buffer; 
       } 
      } 
     } 
    } 
    exit(EXIT_SUCCESS); 
} 

在这种情况下,我尝试运行file “file1的\ nfile2 \ n” 个中3迭代的循环(注意使用了-n -F-标志) ,希望得到半年线,但只有三送:

file1: ERROR: cannot open `file1' (No such file or directory)

file2: ERROR: cannot open `file2' (No such file or directory)

file1: ERROR: cannot open `file1' (No such file or directory)

当我不重定向孩子的输出管道(让它写入std_out),我得到的所有六行。

任何帮助将不胜感激。

+0

您不能保证获得读取所需的字节数。如果您打印出父母正在阅读的字节数,您将看到您正在阅读短文。 – Duck

+0

是的,但为什么我会得到这些短读数?如何获得文件调用输出的所有行? – Paz

回答

0

调度程序。您处于一个循环中,要求孩子(即pgm file)查找两个文件三次。你只能在父文件的每个循环中读一个。

  • 如果孩子被调度并且不间断,它执行第一个文件查找,写入管道,执行第二次查找,写入管道。家长得到安排,你在一次阅读中阅读孩子的完整输出。你是金(但幸运)。
  • 孩子被安排,第一次查找和管道写入并被中断。父母读取一个输出。孩子被重新安排并进行第二次查找并写入管道。父母读取一个输出。因为你只读了3次,你最终只能读出6个输出中的3个。
  • 以上变化。也许你会读1输出然后3然后1.你只是不知道。

请注意,您至少在每次读取时获得完整的子输出的原因是因为如果管道写入在PIPE_BUF长度下(如果它们在PIPE_BUF的长度下),则保证它们是原子。如果你正在使用这种例程,比如套接字,那么你最终可能会在每次读取时得到一小部分消息。

解决方案:您必须循环读取,直到获得您期望的字节数(或完整消息数)。在这种情况下,我假设file的输出总是以换行符结尾的一个字符串。但是您每次通过循环要求输出两个file输出。所以阅读,直到满足条件,即直到你阅读两个完整的字符串。