【Linux】进程间通信——管道详解

每个进程本身具有独立性,故实现进程间通信是有难度的,所以我们要实现进程间通信的前提是想要通信的进程可以“看到”同一份资源(这里主要指同一块内存)。

进程间通信的目的
  1. 数据传输:一个进程需要将它的数据发送给另一个进程
  2. 资源共享:多个进程间需要共享同一份资源。
  3. 通知事件:一个进程需要向其他进程发送消息,通知某个事件。
  4. 进程控制:方便一个进程对另一个进程掌控并及时了解它状态的改变。
进程间通信的方式

1. 管道:主要基于文件,因此生命周期也随文件

匿名管道:用于具有亲缘关系的进程,常用与父子进程间通信。
——用pipe()创建并打开管道
命名管道:通过访问同一文件实现通信,两个进程间可无亲缘关系。
——用mkfifo()创建+open()打开

2. System V IPC:生命周期随内核

System V 共享内存:速度最快;不提供同步互斥机制
System V 消息队列:发送数据块
System V 信号量:自带同步互斥机制

3. POSIX IPC:可移植性强,更加简单
消息队列 共享内存 信号量
互斥量 条件变量 读写锁

管道

我们把从一个进程连接到另一个进程的一个数据流称为一个管道
在这里插入图片描述
管道的特点:

  1. 管道是半双工的即单向通信,若要实现双向通信则需要创建两个管道
  2. 提供流式服务
  3. 内核对管道的操作进行同步与互斥的保证
  4. 进程退出管道及释放,所以管道的生命周期随进程
匿名管道

只能在具有公共祖先的进程间进行通信。
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. 创建命名管道

  1. 命令行:mkfifo filename
  2. 函数: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);

  1. 读取管道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()打开。
  • 两者最大的区别就是打开方式,其他方面的意义相同。

博主将理论和代码分开写了,大家需要了解代码的可以关注博主,或者直接戳下面文章的链接。

使用命名管道实例
进程间通信 — System V IPC

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值