簡體   English   中英

在C中創建管道用於多個進程之間的進程間通信

[英]Creating pipes in C for inter process communication between multiple processes

這個問題已經有多個答案,但沒有一個能夠幫助我解決我的問題。 我試圖在 C 中使用匿名 pipe 來了解 IPC。 根據我對管道的理解,它們是一種單向通信通道,具有一個讀端和一個寫端。
假設我們有兩個 c 文件,一個名為parent.c另一個child.c 我想要實現的是能夠創建 5 個或更多子進程。 在此之后,父進程和子進程應該通過標准輸入和standard output與子進程通信,但是由於我希望能夠打印父進程從子進程收到的內容,因此我將使用dup2將管道連接到standard error output 。
總之
1. 運行一個啟動 5 個或更多子進程並運行它們的父程序。
2. 子進程使用scanf等待來自父進程的輸入。
3. 父進程向子進程發送消息。
4. 子進程收到消息,向父進程發送回復並退出。
5.父進程打印接收到的消息並打印然后退出。

父.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;
}

預期 output

$ ./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

在這里你有一個我做的代碼,我會用它來向你解釋:

#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 示例”命令的結果。 function dup2(new_descriptor, old_descriptor) 正在將新描述符復制到舊描述符中並關閉舊描述符。 例如: 在 dup2(fds[1], 1) 之前,我們有: 0 STDIN 1 STDOUT 2 STDERR 在 dup2(fds[1], 1) 之后,我們有: 0 STDIN 1 fds[1] 2 STDERR 注意:如果你不這樣做不想使用 1,你可以簡單地寫 STDOUT_FILENO 所以現在我們可以通過進程寫入,在我的例子中也可以寫入文件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM