对管道的写操作始终失败

时间:2016-03-20 03:00:56

标签: c linux process pipe

我对管道和并发性有点新意,并且对这个问题感到沮丧数小时。我正在努力理解为什么这个write操作一直在我的管道上失败。我试图让子进程通过父进程将接收的管道写入数据。我目前的代码是:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 4096

int main() {
    pid_t status;
    int fd[2]; //The array of file descriptors

    if (pipe(fd) == -1) {
        printf("Error piping");
    }

    status = fork(); //Begin the fork process
    switch (status) {
        case -1:
            perror("Error forking");
            break;
        case 0:
            //Child process
            close(fd[0]); //Only send data
            char some_string[15] = "hi there";
            if (write(fd[1], some_string, MAXSIZE) == -1) {
                printf("Error writing to the pipe");
            }
            close(fd[1]); //Close write end
            exit(1);
        default:
            close(fd[1]); //Only receive data
            char readed[500] = "";
            while(read(fd[0], readed, MAXSIZE) != 0) {
                printf("read this %s\n", readed);
            }
            printf("Done reading");
            close(fd[0]);
            break;
    }
    return 1;
}

但是,我经常收到消息“写入管道时出错”,这意味着write操作在子进程中失败了。另一个有趣的事情是,如果我将some_string更改为字符串文字,则此代码可以正常工作,但它永远不会终止,而父进程中的read操作将从{{1}读取}!我不明白为什么会发生这种情况,父母执行时我们有一个僵尸孩子,因此管道“死了”?或许父进程终止,我们有一个孤儿?我怎样才能避免这种情况,以及如何解释字符串文字中的奇怪行为呢?任何见解?

1 个答案:

答案 0 :(得分:2)

您告诉write()从数组的超出范围读取数据,并允许read()将读取的数据写入数组的超出范围。这非常糟糕。

仅写入有效数据并限制读取的长度,以免导致超出范围的访问。

试试这个:

#include <unistd.h>
#include <sys/types.h> /* add this to use pid_t */
#include <sys/wait.h> /* add this to use wait() */
#include <stdio.h>
#include <stdlib.h>
/* remove unused MAXSIZE */

int main() {
    pid_t status;
    int fd[2]; //The array of file descriptors
    int st; /* variable for receiving the status */

    if (pipe(fd) == -1) {
        printf("Error piping");
        return 1; /* return 1 when the execution failed */
    }

    status = fork(); //Begin the fork process
    switch (status) {
        case -1:
            perror("Error forking");
            return 1; /* return 1 when the execution failed */
            break;
        case 0:
            //Child process
            close(fd[0]); //Only send data
            char some_string[15] = "hi there";
            if (write(fd[1], some_string, sizeof(some_string)) == -1) {
                printf("Error writing to the pipe");
            }
            close(fd[1]); //Close write end
            exit(0); /* return 0 if the execution finished successfully */
        default:
            close(fd[1]); //Only receive data
            char readed[500] = "";
            while(read(fd[0], readed, sizeof(readed) - 1) != 0) { /* -1 for reserving space for terminating null-character */
                printf("read this %s\n", readed);
            }
            printf("Done reading");
            close(fd[0]);
            wait(&st); /* wait for the child process to exit and release the data of the process */
            break;
    }
    return 0; /* return 0 if the execution finished successfully */
}