概念
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区。进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC)
进程通信是指在进程间传输数据(交换信息)。进程通信根据交换信息量的多少和效率的高低,分为低级通信(只能传递状态和整数值)和高级通信(提高信号通信的效率,传递大量数据,减轻程序编制的复杂度)。其中高级进程通信分为三种方式:共享内存模式、消息传递模式、共享文件模式。
管道
无名管道
一种最基本的ipc机制,由pipe函数创建
#include <unistd.h> int pipe(int filedes[2]);
调用pipe函数时,在内核开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端(单向通信),然后通过filedes参数传出给用户程序两个文件描述符。
filedes[0]:读端。(就像0是标准输入)
filedes[1]:写端。(就像1是标准输出)
/*************************************************************************
> File Name: getPipe.c
> Author:
> Mail:
> Created Time: Fri 28 Jan 2022 01:01:33 PM CST
************************************************************************/
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
int main() {
int pip[2];
if (pipe(pip) < 0) {
perror("pipe");
exit(1);
}
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (!pid) { //在子进程
close(pip[1]); //关闭写端
char* buf[20];
printf("父进程你倒是快点发消息啊!!!\n");
int n = read(pip[0], buf, 20);
write(1, buf, n);
sleep(2);
} else {
//在父进程
close(pip[0]); //关闭读端
sleep(1); //等待1秒我在写
write(1, "我发了呀!!!\n", sizeof("我发了呀!!!\n"));
write(pip[1], "hello child!!!\n", 15);
printf("child你倒是快点死呀!!!\n");
wait(NULL);
}
return 0;
}
使用无名管道的特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志)
- 1、如果所有指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样
- 2、如果有指向管道写端的文件描述符没关闭,而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读取数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读才读取数据并返回。
- 3、如果所有指向管道读端的文件描述符都关闭了,这是有进程向管道的写端write,那么该进程会收到SIGPIPE,通常会导致进程异常终止。
- 4、如果有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有向管道中读取数据,这时有进程向管道写端写数据,那么在管道被写满时,再次write会阻塞,直到管道有空位置才写入数据并返回。
命名管道
https://axieyun.top/posts/16da.html