没有得到管道的所有线路

时间:2014-03-12 21:12:21

标签: c++ linux fork pipe read-write

我正在进行一项任务,我需要一些进程(父进程和子进程)进行通信。 父节点向子节点发送文件路径,它们必须在它们上运行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);
}

在这种情况下,我尝试在“file1 \ nfile2 \ n”上运行file(注意使用的-n -f-标志)在3次迭代的循环中,期望得到6行,但是得到只有三个:

  

file1:错误:无法打开`file1'(没有这样的文件或目录)

     

file2:错误:无法打开`file2'(没有这样的文件或目录)

     

file1:错误:无法打开`file1'(没有这样的文件或目录)

当我没有将孩子的输出重定向到管道(让它写入std_out)时,我确实获得了所有六行。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

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

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

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

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