将数据写入管道后,C应用程序挂起。如何检查" cat"过程完成了吗?

时间:2018-04-16 05:20:47

标签: c pipe buffer fork exec

我的C应用程序我想将数据写入管道进程。接下来,我想要一个文件描述符,其中所有写入的数据都被缓冲。为此,我选择使用cat命令。以下是我的代码(问题的过度简化版本):

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>

#define PIPE_READ 0
#define PIPE_WRITE 1

/*
 * 
 */
int main(int argc, char** argv) {
    int fd[2];
    int childpid;
    int writePntr;
    pipe(fd);
    if ((childpid = fork()) == -1) {
        perror("fork");
    }
    if (childpid == 0) {
        dup2(fd[PIPE_WRITE], STDOUT_FILENO); // send stdout to the pipe
        char a = 'a';
        write(fd[PIPE_WRITE], &a, 1);
        char b = 'b';
        write(fd[PIPE_WRITE], &b, 1);
        write(fd[PIPE_WRITE], '\0', 1);
        close(fd[PIPE_WRITE]);
        close(fd[PIPE_READ]);
        char *cmd = "cat";
        char *argv[2];
        argv[0] = "cat";
        argv[1] = NULL;

        execvp(cmd, argv);
        exit(1);
    } else {
        close(fd[PIPE_WRITE]);
        writePntr = fd[PIPE_READ];
    }
    wait(NULL);
    char readbuffer[1];
    while (read(writePntr, readbuffer, 1) > 0) {
        printf(readbuffer);
    }
    close(writePntr);

    return (EXIT_SUCCESS);
}

此代码存在的问题是它在wait(&childpid);while (read(writePntr, readbuffer, 1) > 0) {上都挂起(如果我删除了wait语句)。它实际上似乎永远循环在while循环中,这意味着过程永远不会因某种原因而结束。

在我的代码的过度简化版本中,我写了字符&#39; a&#39;和&#39; b&#39;到管道,然后是一个NULL终止符(虽然我不确定是否需要)。我相信我关闭了管道的所有必要侧面。在代码的真实版本中,&#39; a&#39;和&#39; b&#39;实际上是写入管道的完整缓冲区。我必须这样做的原因是,我想要单个文件描述符,其中包含附加到另一个文件描述符的所有数据的另一个文件描述符的所有数据。

有谁知道为什么附加的代码会挂起?

2 个答案:

答案 0 :(得分:1)

这是代码,我试着在评论中解释。

int main(int argc, char** argv) {
        int fd[2];
        int childpid;
        int writePntr;
        pipe(fd);
        if ((childpid = fork()) == -1) {
                perror("fork");
        }
        if (childpid == 0) {
                dup2(fd[PIPE_WRITE], STDOUT_FILENO); // send stdout to the pipe
                char a = 'a';
                write(fd[PIPE_WRITE], &a, 1);
                char b = 'b';
                write(fd[PIPE_WRITE], &b, 1);
                write(fd[PIPE_WRITE], '\0', 1);
                dup2(3,0);
                dup2(4,1); /* you must duplicate pipe[1] to stdout */
                char *cmd = "/bin/cat";
                char *argv[2];
                argv[0] = "cat";
                argv[1] = "data";/* data is the file name */
                execlp(cmd, argv[0],argv[1],NULL);
                perror("execvp");

                exit(1);
        } else {
                close(fd[PIPE_WRITE]);
                writePntr = fd[PIPE_READ];
        }
        wait(NULL);
        char readbuffer; /* take only char */
        while (read(writePntr, &readbuffer, 1) > 0) {/* read char by char */
                printf("%c \n",readbuffer);
        }
        close(writePntr);
        return (EXIT_SUCCESS);
}

答案 1 :(得分:0)

查看wait(2)的手册页 - 它可能没有做你认为应该做的事情,也就是等到你创建的子进程终止。

此外,参数是写入已终止进程的状态的位置,而不是您正在等待的进程的PID - 这将是waitpid,这是相关的。

请注意,您正在为孩子和父母调用wait - 因此孩子在死前会等待孩子死亡,并通知其父母。