【问题标题】:Program doesn't stop after reading from pipe从管道读取后程序不会停止
【发布时间】:2017-06-16 18:23:12
【问题描述】:

我正在尝试理解管道。我有这个小程序,它使用管道将消息从父进程发送到其子进程。孩子收到所有 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;
}

【问题讨论】:

    标签: c unix pipe


    【解决方案1】:

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

    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 是明确的。 child 的退出机制似乎也不自然。但我猜这是另一个问题。
    【解决方案2】:

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

    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){
          ...
        }
    }
    

    请记住,在管道上,文件结尾是“管道中没有更多可读取的内容”“没有更多的写入器”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多