每个进程本身具有独立性,故实现进程间通信是有难度的,所以我们要实现进程间通信的前提是想要通信的进程可以“看到”同一份资源(这里主要指同一块内存)。
进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程间需要共享同一份资源。
- 通知事件:一个进程需要向其他进程发送消息,通知某个事件。
- 进程控制:方便一个进程对另一个进程掌控并及时了解它状态的改变。
进程间通信的方式
1. 管道:主要基于文件,因此生命周期也随文件
匿名管道:用于具有亲缘关系的进程,常用与父子进程间通信。
——用pipe()创建并打开管道
命名管道:通过访问同一文件实现通信,两个进程间可无亲缘关系。
——用mkfifo()创建+open()打开
2. System V IPC:生命周期随内核
System V 共享内存:速度最快;不提供同步互斥机制
System V 消息队列:发送数据块
System V 信号量:自带同步互斥机制
3. POSIX IPC:可移植性强,更加简单
消息队列 共享内存 信号量
互斥量 条件变量 读写锁
管道
我们把从一个进程连接到另一个进程的一个数据流称为一个管道
管道的特点:
- 管道是半双工的即单向通信,若要实现双向通信则需要创建两个管道
- 提供流式服务
- 内核对管道的操作进行同步与互斥的保证
- 进程退出管道及释放,所以管道的生命周期随进程
匿名管道
只能在具有公共祖先的进程间进行通信。
1. 创建匿名管道
#include <unistd,h>
int pipe(int fd[2]);
其中fd 是大小为2 的文件描述符数组,fd[0]表示读端, fd[1]表示写端
成功返回0,失败返回错误码
读取管道内容
read(fd[0],buf,sizeof(buf)-1);
若返回值>0表示所读大小,若返回值=0表示文件读完,若返回值<0表示读取失败
向管道内写入
write(fd[1],buf,strlen(buf));
2. 用fork() 共享管道的原理
3. 站在文件描述符的角度理解管道
4. 管道读写规则
- 当前没有数据可读时,即read要读而write未写时,read会被阻塞。
- 当前管道已被写满,即write要写而read不读时,write被阻塞。
- 若管道写端被关闭,则read返回0。因为不会发生写入所以类似读到文件末尾。
- 若管道读端被关闭,则write退出。因为此时写入无任何意义,所以被OS退出。
- 若写入数据不大于PIPE_BUF(4k~8k),Linux会保证写入的完整性。
命名管道
通过访问同一个文件实现进程间通信,是一个特殊类型的文件。
1. 创建命名管道
- 命令行:mkfifo filename
- 函数:
int mkfifo(const char*filename,mode_t mode);
2. 管道打开规则
- 若用读操作打开FIFO,则read被阻塞,直到有进程为write而打开。
立即返回成功 - 若用写操作打开FIFO,则write被阻塞,直到有进程为read而打开。
立即返回失败
3. 例1:用命名管道实现文件拷贝的过程
我用一个将“abc”文件拷贝至“abc.bak”中的过程,深刻理解一下命名管道的工作原理
1)读取“abc”中的内容写入管道tp 中,实现的主要代码
mkfifo(“tp”,0644);
int infd=open(“abc”,O_RDONLY);
int outfd=open(“tp”,O_WRONLY);
while(n=read(infd,buf,1024)
write(outfd,buf,n);
- 读取管道tp 写入目标文件"abc.bak"中,实现的主要代码
outfd=open(“abc.bak”,O_CREAT);
infd=open(“tp”,O_RDONLY);
while(n=read(infd,buf,1024)
write(outfd,buf,n)
实现的完整代码:在下篇博客中呈现,大家可以戳链接哦~
使用命名管道实例:https://blog.csdn.net/ly_6699/article/details/97310441
例2:用命名管道实现serve和client 的通信
这里我将实现serve 从一端写入信息,client从另一端读取并打印消息到显示器上。
如下:
实现的完整代码:在下篇博客中呈现,大家记得戳链接哦~
https://blog.csdn.net/ly_6699/article/details/97310441
4.匿名管道和命名管道的区别
- 匿名管道需要pipe()创建并打开;命名管道FIFO需要mkfifo()创建+open()打开。
- 两者最大的区别就是打开方式,其他方面的意义相同。
博主将理论和代码分开写了,大家需要了解代码的可以关注博主,或者直接戳下面文章的链接。