使用管道读写

Read and write using pipes

我有一个包含 2 个 child 进程的程序,它必须执行以下操作:

我试过了,效果不错……有点。问题是,它将过滤后的字母写入所需的文件,但程序不会停止。我做错了什么?

    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <string.h>
    
    int parentChildpipeFileDescriptors[2], child1Child2FileDescriptors[2];
    
    void parentProcess()
    {
        close(child1Child2FileDescriptors[0]);
        close(child1Child2FileDescriptors[1]);
        close(parentChildpipeFileDescriptors[0]);
    
        int fileDescriptor = open("data.txt", O_RDONLY);
        char buffer[8];
        int store;
        while ((store = read(fileDescriptor, buffer, 8)))
        {
            write(parentChildpipeFileDescriptors[1], buffer, store);
        }
        close(fileDescriptor);
    
        close(parentChildpipeFileDescriptors[1]);
    }
    
    void child1Process()
    {
        close(parentChildpipeFileDescriptors[1]);
        close(child1Child2FileDescriptors[0]);
    
        char buffer[8];
        int store, count = 0;
        while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))
        {
            for (int i = 0; i < store; i++)
            {
                if (buffer[i] >= 'a' && buffer[i] <= 'z')
                {
                    count++;
                    write(child1Child2FileDescriptors[1], &buffer[i], sizeof(buffer[i]));
                }
            }
        }
        printf("CHILD 1 FINISHED FILTERING\n");
    
        close(parentChildpipeFileDescriptors[0]);
        close(child1Child2FileDescriptors[1]);
    
        exit(count);
    }
    
    void child2Process()
    {
        close(parentChildpipeFileDescriptors[0]);
        close(child1Child2FileDescriptors[1]);
    
        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
        char *fileName = "stat.txt";
        int newFileDescriptor = creat(fileName, mode);
        char buffer;
        int store;
        while ((store = read(child1Child2FileDescriptors[0], &buffer, 1)))
        {
            write(newFileDescriptor, &buffer, sizeof(buffer));
            write(newFileDescriptor, "\n", 1);
        }
        close(newFileDescriptor);
    
        printf("CHILD 2 FINISHED WRITING'\n");
    
        close(child1Child2FileDescriptors[0]);
        close(parentChildpipeFileDescriptors[1]);
    
        exit(444);
    }
    
    int main(int argc, char const *argv[])
    {
        if (pipe(parentChildpipeFileDescriptors) < 0)
        {
            printf("ERROR CREATING PIPE\n");
            exit(-100);
        }
    
        if (pipe(child1Child2FileDescriptors) < 0)
        {
            printf("ERROR CREATING PIPE\n");
            exit(-101);
        }
    
        pid_t child1PID = fork();
        if (child1PID < 0)
        {
            printf("ERROR CREATING CHILD\n");
            exit(-200);
        }
        if (!child1PID)
        {
            child1Process();
        }
    
        pid_t child2PID = fork();
        if (child2PID < 0)
        {
            printf("ERROR CREATING CHILD\n");
            exit(-201);
        }
        if (!child2PID)
        {
            child2Process();
        }
    
        parentProcess();
        int status1, status2;
        waitpid(child1PID, &status1, 0);
        waitpid(child2PID, &status2, 0);
        printf("CHILD 1 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status1));
        printf("CHILD 2 TERMINATED WITH EXIT STATUS: %d\n", WEXITSTATUS(status2));
    
        return 0;
    }

你的 while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8))) 循环永远不会结束。

parent 需要告诉 child 没有更多的数据来了,它不会再读了。 你可以通过发送一个特殊的字节来做到这一点。

示例:

在parent:

char endByte = 0x1;
write(parentChildpipeFileDescriptors[1], &endByte, 1);
//then close

在 child 的 while 循环中:

if(buffer[i] ==  0x1){
    printf("CHILD 1 FINISHED FILTERING\n");
    fflush(stdout);
    close(parentChildpipeFileDescriptors[0]);
    close(child1Child2FileDescriptors[1]);

    exit(count);
};

child1process 中的读取循环将永远不会终止,因为 child2 仍然打开该管道的写入端。你需要执行:

close(parentChildpipeFileDescriptors[1]);

在进入读取循环之前。一般规则是,如果进程不打算使用文件描述符,则应立即将其关闭。