在C中创建管道以在多个进程之间进行进程间通信

问题描述 投票:-1回答:1

此问题已经有多个答案,但没有一个能够帮助我解决问题。我正在尝试使用C中的匿名管道来了解IPC。从我对管道的理解来看,它们是一种具有一个读取端和一个写入端的单向通信通道。假设我们有两个c文件,一个名为parent.c,另一个名为child.c。我试图实现的目标是能够创建5个或更多子进程。此后,父级和子级应该通过标准输入和standard output与子级进程进行通信,但是由于我希望能够打印父级从子级收到的内容,因此我将使用以下方法将管道绑定到standard error输出dup2摘要1.运行一个父程序,它启动5个或更多子进程并运行它们。2.子进程使用scanf等待来自父进程的输入。3.父级向子进程发送一条消息。4.子进程接收到该消息,并向父进程发送回复并退出。5.父进程打印收到的消息并打印,然后退出。

parent.c

// Parentc
#include <stdio.h>
#include <stdlib.h>
#include <uinstd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, const char *argv[]){
        // File descriptors for the pipes
        int read_pipe[2]; // From child to parent
        int write_pipe[2]; // From parent to child

        pid_t process_id;
        int exit_status;

        // Try to fork 5 child processes
        for(int i = 0; i < 5; i++){
                if(pipe(write_pipe) == -1 || pipe(read_pipe == -1)){
                        perror("Pipe");
                        exit(1);
                }

                // Spin a child process
                process_id = fork();

                if(process_id == -1){
                        perror("Fork");
                        exit(1);
                } else if(processId == 0) {
                        // The child process
                        // I don't know what to do here, The idea is to close the
                        // unneeded end of the pipes and wait for input from the parent
                        // process

                         // Start the ./child
                        execl("./child", "");            

                } else {
                        // The parent process
                        char recieved_data[1024];

                        // Send data to child since stderr is duplicated in the pipe
                        // It sends the pid of the child
                         fprintf(stderr, "Test data to %d ", process_id);

                        // Wait to recieve data from child
                        // Don't know how to do that

                         // Print the recieved data
                        printf("Parent recieved: \"%s\"\n", recieved_data);

                        wait(&exit_status); // Will wait till all children exit before exiting
                }
        }

        return 0;
}

child.c是一个简单的程序,如下所示

child.c

#include <stdio.h>

int main(int argc, const char *argv[]){
        char data_buffer[1024];

        // Wait for input from parent
        scanf("%s", data_buffer);

        // Send data back to parent
        printf("Child process: %s", data_buffer);

        return 0;
}

预期输出

$ ./parent
parent recived: "Child process: Test data to 12345"
parent recived: "Child process: Test data to 12346"
parent recived: "Child process: Test data to 12347"
parent recived: "Child process: Test data to 12348"
parent recived: "Child process: Test data to 12349"

其中12345、12346 .... 12349是子进程的进程ID

c linux multithreading pipe ipc
1个回答
0
投票

您在这里有一个代码,我会用它来向您解释:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    char buff[1024];
    int aux, i, count;
    int fds[2], fdss[2];
    pipe(fds); //Here we initialize the file descriptors
    pipe(fdss);
    mode_t fd_mode = S_IRWXU;

    for (i = 0; i < 3; i++) {
        aux = fork();
        if (aux == 0)
            break;
    }

    switch (i) {

        case 0:
            printf("Write something:\n");
            scanf("%s[^\n]", buff);
            i = 0;
            count = 0;
            while(buff[i] != '\0') {

                count++;
                i++;
            }
            dup2(fds[1], 1);
            close(fds[1]);
            close(fds[0]);
            close(fdss[0]);
            close(fdss[1]);
            write (1, buff, sizeof(buff));
            break;

        case 1:

            dup2(fds[0], 0);
            dup2(fdss[1], 1);
            close(fds[0]);
            close(fds[1]);
            close(fdss[0]);
            close(fdss[1]);
            // 
            if (execl("/bin/grep", "grep", "example", NULL) == -1) {
                printf("Error\n");
                exit (1);
            }

            break;

        case 2:
            aux = open("result.txt", O_RDWR | O_CREAT , S_IRWXU);

            dup2(fdss[0], 0);
            dup2(aux, 1);
            close(fds[0]);
            close(fds[1]);
            close(fdss[0]);
            close(fdss[1]);
            close(aux);
            if (execl("/usr/bin/wc", "wc", "-l", NULL) == -1) {
                printf("Error \n");
                exit (1);
            }

    }
            close(fds[0]);
            close(fds[1]);
            close(fdss[0]);
            close(fdss[1]);
    for (i = 0; i < 3; i++) wait(NULL);

    return 0;
}

好,我们开始:我们使用pipe()创建和初始化管道然后,我们编写代码,并在execl()之前更改文件描述符,为了传递文本,我们将通过进程编写文本,最后在名为result.txt的文件中写入“ grep example”命令的结果,并将其应用于我们已经在控制台中写了函数dup2(new_descriptor,old_descriptor)将新描述符复制到旧描述符中并关闭旧描述符。例如:在dup2(fds [1],1)之前,我们有:0 STDIN1个标准输出2个标准差在dup2(fds [1],1)之后,我们得到:0 STDIN1 fds [1]2个标准差注意:如果您不想使用1,可以直接写STDOUT_FILENO因此,现在我们可以将过程写成文件,在我的示例中也可以写到文件中

© www.soinside.com 2019 - 2024. All rights reserved.