C - Unix管道,close()会影响输出吗?

时间:2015-11-08 06:02:21

标签: c unix pipe

使用unix管道时遇到了一个奇怪的错误。我写了一个简短的程序来展示这个问题。

以下是代码:

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>


int main(int argc, char*args[]){
    int fd[2];
    pipe(fd);
    int pid = fork();
    if(pid<0){
        perror("fork()");
        exit(1);
    }else if(pid == 0){
        close(fd[0]);
        const char* msg = "I'm here\n";
        size_t len = strlen(msg) + 1; // +1 for null char
        write(fd[1], msg, len);
        while(1){/*does other work*/}
    }else{
        close(fd[1]);
    }
    pid = fork();
    if(pid<0){
        perror("fork()");
        exit(1);
    }else if(pid == 0){
        close(fd[0]);
        const char* msg = "I'm here\n";
        size_t len = strlen(msg) + 1; // +1 for null char
        write(fd[1], msg, len);
        while(1){/*does other work*/}
    }else{
        close(fd[1]);
    }
    //close(fd[1]);
    sleep(5);

    const char* msg = "I'm here\n";
    size_t len = strlen(msg) + 1; // +1 for null char
    char str[len];
    fcntl(fd[0],F_SETFL, O_NONBLOCK);
    if(read(fd[0], str, len)<=0){
        printf("Nothing from child\n"); 
    }
    /*does other work*/
    fcntl(fd[0],F_SETFL, O_NONBLOCK);
    if(read(fd[0], str, len)<=0){
        printf("Nothing from child\n"); 
    }
    printf("finished read\n");
    /*does other work*/
    wait(NULL);
    return 0;
}

父进程分叉两个子节点并创建一个管道。两个子进程写入管道,父管道从管道读取。

父进程应该恢复子进程写的所有信息。

但是,当我运行上述程序时,父打印出来

Nothing from child
finished read

为什么?

有趣的是,如果我写一个关闭(fd [1]),就像这样:

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>


int main(int argc, char*args[]){
    int fd[2];
    pipe(fd);
    int pid = fork();
    if(pid<0){
        perror("fork()");
        exit(1);
    }else if(pid == 0){
        close(fd[0]);
        const char* msg = "I'm here\n";
        size_t len = strlen(msg) + 1; // +1 for null char
        write(fd[1], msg, len);
        while(1){/*does other work*/}
    }else{

    }
    pid = fork();
    if(pid<0){
        perror("fork()");
        exit(1);
    }else if(pid == 0){
        close(fd[0]);
        const char* msg = "I'm here\n";
        size_t len = strlen(msg) + 1; // +1 for null char
        write(fd[1], msg, len);
        while(1){/*does other work*/}
    }else{

    }
    close(fd[1]);//HERE IS THE DIFFERENCE
    sleep(5);

    const char* msg = "I'm here\n";
    size_t len = strlen(msg) + 1; // +1 for null char
    char str[len];
    fcntl(fd[0],F_SETFL, O_NONBLOCK);
    if(read(fd[0], str, len)<=0){
        printf("Nothing from child\n"); 
    }
    /*does other work*/
    fcntl(fd[0],F_SETFL, O_NONBLOCK);
    if(read(fd[0], str, len)<=0){
        printf("Nothing from child\n"); 
    }
    printf("finished read\n");
    /*does other work*/
    wait(NULL);
    return 0;
}

它有效,如果我根本不接近(fd [1])也可以。我迷路了,为什么close()的位置会影响管道的读数?

1 个答案:

答案 0 :(得分:1)

我不确定这是不是你的问题,但这句话显然是错误的:

write(fd[1], "I'm here\n", 256);

您正在从源缓冲区写入256个字节,这是一个非常短的静态字符串。我想你想这样说:

const char* msg = "I'm here\n";
size_t len = strlen(msg); // could be strlen(msg)+1 - see discussion in comments.
write(fd[1], "I'm here\n", len);