繁体   English   中英

没有从管道中获得所有管线

[英]Not getting all the lines from a pipe

我正在做一个作业,需要一些流程(父母和孩子)进行沟通。 父级将文件路径发送给子级,并且子级必须在子级上运行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);
}

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

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

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

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

当我不将孩子的输出重定向到管道(将其写入std_out)时,我确实得到了全部六行。

任何帮助将不胜感激。

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

  • 如果子进程已调度且不间断,则它将执行第一个文件查找,写入管道,执行第二次查找,写入管道。 父母安排好了,您一次阅读了孩子的全部输出。 你是金色的(但很幸运)。
  • 子进程已安排好,进行第一次查找和管道写入并被中断。 父级读取一个输出。 子级被重新安排并进行第二次查找并写入管道。 父级读取一个输出。 因为您只读取3次,所以最终只能读取6个输出中的3个。
  • 上面的变化。 也许您会读到1个输出,然后读3个,然后读1个。您只是不知道。

请注意,至少每次读取都获得完整的子级输出的原因是,如果管道写操作的长度小于PIPE_BUF,则保证它们是原子的。 如果在套接字上使用这种例行程序,则每次读取时最终可能会得到消息的一部分。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM