进程间通信

40 阅读2分钟

通过管道进行通信

管道属于操作系统

image.png

int pipe(int filedes[2]);
成功返回 0, 失败返回-1
filedes[0]: 通过管道接收数据时使用的文件描述符,即管道出口
filedes[1]: 通过管道传输数据时使用的文件描述符,即管道入口

父进程调用该函数创建管道,同时获取对应的出入口文件描述符。为了与子进程通信,需要将入口或者出口中的文件描述符传给子进程,通过fork()函数传递。


#define BUF_SIZE 30

int main(int argc, char *argv[]) {
    int fds[2];
    char str[] = "who are you?";
    char buf[BUF_SIZE];
    pid_t pid;
    
    pipe(fds); //调用成功后,fds 会同时保存父子进程的 socket 文件描述符
    pid = fork();
    if (pid == 0) {
        //子进程仅用输入路径
        write(fds[1], str, sizeof(str));
    } else {
        //父进程仅用输出路径
        read(fds[0], buf, BUF_SIZE);
        puts(buf);
    }
    return 0;
}

父子进程都可是访问管道的 I/O 路径,倒是子进程仅用输入路径,父进程仅用输出路径。

image.png

通过管道进行进程间双向通信

image.png

#define BUF_SIZE 30

int main(int argc, char *argv[]) {
    int fds[2];
    char str1[] = "who are you?";
    char str2[] = "thank you for your message";
    char buf[BUF_SIZE];
    pid_t pid;

    pipe(fds);
    pid = fork();
    if (pid == 0) {
        write(fds[1], str1, sizeof(str1));
        sleep(2); //防止子进程把自己 write 的读取
        read(fds[0], buf, BUF_SIZE);
        printf("child proc output: %s \n", buf);
    } else {
        //接收子进程传过来的数据
        read(fds[0], buf, BUF_SIZE);
        printf("parent proc output: %s \n", buf);
        //向子进程传输数据
        write(fds[1], str2, sizeof(str2));
        sleep(3);
    }
    return 0;
}

向管道传递数据时,先读的进程会把数据取走,数据进入管道后成为无主数据,哪个进程先调用read()函数进行读取,就先获取到这个数据。

因此,可以创建 2 个管道进行通信

image.png

fds1 数据入口,write

fds0 数据出口,read

int main(int argc, char *argv[]) {
    int fds1[2], fds2[2];
    char str1[] = "who are you?";
    char str2[] = "thank you for your message";
    char buf[BUF_SIZE];
    pid_t pid;

    pipe(fds1);
    pipe(fds2);
    pid = fork();
    if (pid == 0) {
        write(fds1[1], str1, sizeof(str1));
        read(fds2[0], buf, BUF_SIZE);
        printf("child proc output: %s \n", buf);
    } else {
        read(fds1[0], buf, BUF_SIZE);
        printf("parent proc output: %s \n", buf);
        write(fds2[1], str2, sizeof(str2));
        sleep(3);
    }
    return 0;
}