父进程无法读取管道

时间:2017-09-24 18:25:55

标签: c file pipe fork

在这个论坛中有很多与管道读写有关的问题,但我无法解决我的问题。 下面的代码片段包含以下内容:

  1. 通过命令行参数filename通过pipe_p
  2. 传递给子进程
  3. 子进程打开指定的文件,并将其内容写入pipe_c,以便父进程读取并显示在屏幕上。
  4. 一切正常,但父进程无法从管道中读取数据(因为它没有打印任何内容)。 我观察到数据是由子进程成功编写的,因为我能够通过子进程块中的管道打印内容,但不能在父进程中打印。

    注意:STEP 4无法正常工作

    任何人都可以帮助我。

    代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char **argv){
    
        int pipe_p[2], pipe_c[2];
        int childpid, c, k = 0;
        char buffer[1000] = {0};
        FILE *file;
    
        pipe(pipe_p);
        pipe(pipe_c);
    
        childpid = fork();
    
        if(childpid){
            //parent process block
            //STEP 1 -------
            close(pipe_p[0]);   //closing reading side of pipe
            write(pipe_p[1], argv[1], strlen(argv[1]));
            close(pipe_p[1]);
            //--------------
            wait(NULL);
            //--------------
            //printf("%s\n", "Its working");
            //STEP 4 -------
            close(pipe_c[1]);
            read(pipe_c[0], buffer, sizeof(buffer));
            close(pipe_c[0]);
            printf("%s\n", buffer);
            //--------------
        }
        else{
            //child process block
            //sleep(1);
            //STEP 2 -------
            close(pipe_p[1]);
            read(pipe_p[0], buffer, sizeof(buffer));
            close(pipe_p[0]);
            //printf("%s\n", buffer);
            //--------------
    
            //STEP 3 -------
            file = fopen(buffer, "r");
            while((c = getc(file)) != EOF){
                buffer[k++] = c;
            }
            buffer[k] = 0;
            //printf("%s", buffer);
            close(pipe_c[0]);
            write(pipe_c[1], buffer, strlen(buffer));
            close(pipe_c[1]);
            //--------------
        }
    
        return 0;
    }
    

1 个答案:

答案 0 :(得分:1)

我在这段代码中看到了五个错误。我将从最不重要到最重要的列出它们。我没有尝试修复任何错误,因此可能有更多隐藏在这些错误背后。

  • 您忘记加入sys/wait.h。编译器应该抱怨wait的隐式声明。 (如果您的编译器没有提出任何投诉,请打开所有警告。)

  • 您没有检查是否有任何系统调用失败。 每次系统调用之后都应检查失败。当一个失败时,打印到stderr失败的完整描述,包括失败的系统调用的名称,涉及的所有文件的名称(如果有的话)和strerror(errno)然后退出具有非零(不成功)退出代码的程序。如果你这样做了,你就会发现,事实上,某些事情 “工作正常”。

  • 相关地,您没有检查孩子是否退出失败。父级应该执行wait(NULL)而不是waitpid(childpid, &status, 0),然后解码退出状态并向stderr打印除WIFEXITED(status) && WEXITSTATUS(status) == 0以外的任何内容的消息,然后自己退出失败。< / p>

  • 在父级中,您在错误的位置呼叫wait。您需要在阅读并处理wait的所有数据后致电pipe_c。否则,如果子进程完全填满管道缓冲区,程序将死锁。 (另外,您需要从管道中读取所有数据,而不仅仅是它的前1000个字节。)

  • 在孩子中,你有一个缓冲区溢出。您正在从文件中将无限量的数据读入buffer,但buffer具有固定的大小。您应该根据需要使用mallocrealloc进行放大,或者将文件从文件复制到不超过buffer大小的数据包。

我通过strace实用程序在-f模式下运行程序(因此它跟踪fork的两侧),并使用大文件的输入来发现所有这些问题。这是一种有价值的调试技术,您应该亲自尝试。

相关问题