从管道读取后程序不会停止

时间:2017-01-31 10:40:55

标签: c unix pipe

我想了解管道。我有这个小程序,它使用管道从父进程向其子​​进程发送消息。孩子接收了所有3条消息,但在阅读完最后一条消息后,它不会退出。我究竟做错了什么?感谢。

PS:我注意到,如果我在父母的while循环中睡2秒钟,那就可以了。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(){

    int desc[2];
    pipe(desc);

    int pid = fork();

    if(pid == 0){
        while(1){
            sleep(1);
            char buffer[16];
            if(read(desc[0], buffer, 16) != 16){
                printf("Error or finished");
                exit(0);
            };
            printf("Child: message recieved - '%s'\n", buffer);
        }
        close(desc[1]);
    }
    if(pid > 0){
        int i=0;
        while(i <= 2){
            char buffer[100];
            i++; char x[10];
            strcpy(buffer, "Hello, child!");
            sprintf(x, " %d", i);
            strcat(buffer, x);
            if(write(desc[1], buffer, 16) != 16){
                printf("Error");
                exit(0);
            };
        }
        close(desc[0]);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:3)

您必须正确关闭管道末端。读取器将挂起,直到管道的所有写入端都关闭。

if(pid == 0){
    close(desc[1]); // close write end in reader
    while(1){
        ...
        read(desc[0], buffer, 16);
        ...
    }
}
if(pid > 0){
    int i=0;
    close(desc[0]); // close read end in writer; not required, but makes code cleaner
    while(i <= 2){
      ...
      write(desc[1], buffer, 16);
      ...
    }
    close(desc[1]); // close write end in writer
}

答案 1 :(得分:3)

您忘记关闭父母和孩子中管道的无用端。实际上你的孩子拥有阅读和写入管道的一部分,因此他无法检测文件的结尾,因为存在一个编写器(本身!),所以它在读取时被阻止。将您的代码更改为:

if(pid == 0){
    close(desc[1]); // Child is not a writer, so close the write part immediately!
    while(1){
      ...
    }
}
if(pid > 0){
    close(desc[0]); // Parent is not a reader, so close the read part immediately!
    int i=0;
    while(i <= 2){
      ...
    }
}

请记住,在管道上,文件结尾是&#34;在管道中没有其他内容可以读取#34; &#34;没有更多的作家&#34;。