2017-09-24 72 views
0

在此论坛中有许多与读写管道有关的问题,但我无法解决我的问题。 下面的代码片段,并以下的事情:父进程无法读取管道中的子进程写入的数据

  1. 通过命令行参数的文件名是通过pipe_p传递给子进程
  2. 子进程打开指定的文件,并将它的内容pipe_c父进程阅读并在屏幕上显示。

一切工作正常,但父进程无法从管道读取数据(因为它不打印任何东西)。 我观察到数据被成功写入子进程,因为我能够通过管道在子进程块中打印内容,但不能在父进程中打印内容。

注意:步骤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

我看到在这个五级典的错误。我将把它们从最不重要的列表中列出。我没有尝试修复任何错误,所以可能会有更多隐藏在这些错误之后的东西。

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

  • 您不检查是否有任何系统调用失败。 每个系统调用后都应该检查失败。如果发生故障,请打印至stderr有关故障的完整说明,包括失败的系统调用名称,涉及的所有文件的名称(如果有)以及strerror(errno),然后用非零(不成功)退出程序退出码。如果你已经这样做了,那么你会发现,事实上,某些事情是而不是“正常工作”。

  • 相关地,您不检查孩子是否退出失败。而不是wait(NULL),父应该做waitpid(childpid, &status, 0),然后解码退出状态并打印一条消息到stderr以外的任何东西WIFEXITED(status) && WEXITSTATUS(status) == 0,然后退出本身失败。

  • 在父项中,您在错误位置调用wait。您需要拨打wait后您已经阅读并处理了所有pipe_c的数据。否则,如果子进程完全填满管道缓冲区,程序将会死锁。 (另外,你需要从管道中读取数据的所有,而不只是第1000个字节的吧。)

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

我的下strace工具运行的程序,在-f模式(所以它追溯了叉的两侧),从一个大的文件输入发现所有这些问题。这是一个有价值的调试技术,您应该自己尝试。

+0

感谢您的建议@zwol。我没有得到你的第四点,在这里我让父进程等到子进程完成填充缓冲区(这是成功完成的,你可以通过取消printf部分的注释来查看其他部分)。但是在返回到父上下文之后,如果我在其他部分中复制了STEP 4,则不会读取在子进程中读取的数据。 –

+0

好的,我会检查你的编辑。如果你能使代码工作,那将是非常好的。谢谢 –

+0

@ChanchalRoshan修复孩子的缓冲区溢出,然后使用一个_large_测试文件(至少32KB),你应该看到从等待过早的死锁。现在,死锁被缓冲区溢出所掩盖,这使得孩子在填充管道缓冲区之前崩溃。 – zwol

相关问题