简体   繁体   English

使用管道读写

[英]Read and write using pipes

I have a program with 2 child processes which has to do the following:我有一个包含 2 个子进程的程序,它必须执行以下操作:

  • use the parent to read data from a file 'data.txt' and write in a pipe使用父级从文件“data.txt”中读取数据并写入管道
  • use a child to read the data from the pipe and filter the lowercase letters使用孩子从管道中读取数据并过滤小写字母
  • use another child to write the filtered letters in a new file, each on a new line使用另一个孩子将过滤后的字母写在一个新文件中,每个字母都在一个新行上

I tried to do it and it works... kinda.我试着去做,它的工作原理......有点。 The problem is, it writes the filtered letters in the desired file, but the program does not stop.问题是,它将过滤后的字母写入所需的文件,但程序并没有停止。 What am I doing wrong?我究竟做错了什么?

    #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;
    }

The read loop in child1process will never terminate, because child2 still has the write side of that pipe open. child1process 中的读取循环永远不会终止,因为 child2 仍然打开该管道的写入端。 You need to execute:你需要执行:

close(parentChildpipeFileDescriptors[1]);

before you enter the read loop.在进入读取循环之前。 The general rule is that if a process isn't going to use a file descriptor, it should close it immediately.一般规则是,如果一个进程不打算使用文件描述符,它应该立即关闭它。

your while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8))) loop is never gonna end.你的while ((store = read(parentChildpipeFileDescriptors[0], buffer, 8)))循环永远不会结束。

The parent needs to say to the child that there is no more data coming and it shall not do another read.父母需要告诉孩子没有更多的数据来了,它不会再读了。 You can do this by sending a special byte.您可以通过发送一个特殊字节来做到这一点。

Example :例子 :

in the parent:在父母中:

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

in the while loop of the child :在孩子的while循环中:

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

    exit(count);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM