概述
进程间通信(IPC)
- 一、进程间通信(IPC)是什么?
- 二、四种通信方式
- 1.管道-PIPE
- (1)管道分类
- (2)接口
- (3)特性总结
- (4)管道符的实现
- (5)管道总结
- 2. 共享内存
- (1)特性
- (2)速度快
- (3)本质原理
- (4)操作流程
- (5)共享内存总结
- 3.消息队列
- (1)本质
- (2)特性
- 4.信号量
- (1)本质
- (2)作用
- (3)如何实现保护操作
- (4)信号量实现同步与互斥原理
一、进程间通信(IPC)是什么?
操作系统为用户提供的几种用于进程间进行通信的方式。
(管道,共享内存,消息队列,信号量)
目的:进程具有独立性。
(每个进程都有自己的虚拟地址空间,访问的都是自己的虚拟地址,将一个数据的地址就算交给其他进程,其他进程在自己的虚拟地址空间映射中实际上是没有这个数据的);
因此进程间无法直接通信,但是在以后的中大型项目中多个进程协同工作很常见,则进程间通信就尤为重要。
进程间通信根据不同的应用场景,使用不同方式。
二、四种通信方式
1.管道-PIPE
生活中的管道:自来水管,天然气管道,目的都是传输资源;
且在传输资源中具有半双工通信的特性。
半双工通信: 可以选择方向的单向通信。(数据出发端由用户决定)。
作用: 用于实现进程间的数据传输
本质: 内核中的一块缓冲区(内存),多个进程访问同一个缓 冲区实现通信。
(1)管道分类
外在用法不同,但是本质相同
①匿名管道:内核中开辟的这块缓冲区,没有标识符,无法被其他进程找到(只能用于具有亲缘关系的进程间通信)
②命名管道:内核中开辟的这块缓冲区,有标识符,能被其他进程找到(可用于同一主机上任意进程间通信)
一个进程通过系统调用在内核中创建了一个匿名管道,为了能让用户操控这个管道,因此返回了文件描述符作为这个管道的操作句柄。
其他进程因为没有这个管道标识符,所以无法通信;
但是,如果这个创建管道的进程创建了一个子进程,这时候子进程复制了父进程(文件描述信息表),所以子进程相当于也有文件描述符可以操作该管道
—匿名管道只能用于具有亲缘关系的进程间通信。
只有通过子进程复制父进程才能获取到同一个管道的操作句柄。
命名管道: 一个进程创建一个命名管道,这个命名管道会在文件系统中创建出一个管道文件(可以看得到的,实际上就是管道的名字),多个进程通过打开同一个管道文件,访问内核中同一个缓冲区实现通信。
注意:命名管道文件只是一个文件,是为了让进程找到同一个缓冲区。
(2)接口
匿名管道的创建:
int pipe(int pipefd[2]);
pipefd[2]:具有2个int元素的数组,用于接收管道创建成功所返回的文件描述符-操作句柄
pipefd[0]:用于从管道中读取数据;
pipefd[1]:用于从管道写入数据
返回值:成功返回0;失败返回-1;
注意:匿名管道的创建一定要在创建子进程之前,才能被子进程复制到操作句柄
管道的读写特性:
如果管道中无数据,则read会阻塞;
如果管道中数据满了,则write会阻塞.
阻塞:为了完成一个功能,发起调用,功能无法完成则调用一直等待;
非阻塞:为了完成一个功能,发起调用,功能无法完成则调用报错返回;
其他特性:
管道的操作是会阻塞的,但是如果管道所有写端被关闭
(管道已经不可能写入数据),这时候read读取完管道中的数据后,就不再阻塞了,而返回0(表示没人写入了,而不是没数据了)。
管道的所有读端被关闭(管道没人读取数据),
则继续write就会触发异常,进程退出。
(3)特性总结
①半双工通信
②没有数据read阻塞;数据满了write阻塞
③所有读端关闭,则write触发异常,进程退出
④所有写段关闭,则read读完数据后不再阻塞,返回0
shell中的管道符的实现: ps -ef|grep***
管道符:连接两个命令,将前面命令的输出结果,作为后面命令的输入传递给后面命令进行处理。
ps-ef
: ps进程,功能是将所有的进程信息打印出来(写入到标准输出)
grep ssh
: grep进程,不断捕捉标准输入数据进行字符串匹配后输出;
(4)管道符的实现
让前面的命令进程,不再写入数据到标准输出,而是写入管道中
让后面的命令进程,不再从标准输入读取数据,而是从管道读取
- 创建一个管道
- 创建ps进程(创建一个子进程,程序替换为ps),
在程序替换前,将标准输出重定向到管道 - 创建grep进程(创建一个子进程,子进程替换为grep),
在程序替换前,将标准输入重定向到管道 - 等待命令子进程退出。
匿名管道:
(1)本质:内核中的一块缓冲区(没有标识符)
(2)操作:int pipe(int pipefd[2])
(3)特性:
半双工通信;
①数据先进先出(流式传输);
②管道没有数据read阻塞,数据满了write阻塞;
③所有读端关闭write触发异常,所有写端关闭则read返回0;
④只能用于具有亲缘关系的进程间通信。
命名管道:
可以用于同一主机上的任意进程间通信
(1)本质:
内核中的一块缓冲区(但是具有一个可见于文件系统的管道文件作为名字,多个进程通过打开同一个管道文件访问同一个管道)
(2)原理:
管道的缓冲区在没有进程确定要写数据且有进程读取数据的情况下,缓冲区就没必要开辟,空占资源
(3)操作:
命令:mkfifo filename 创建命名管道文件
接口:int mkfifo(char *filename,mode_t mode);
创建命名管道文件,并不会立即创建内核中的缓冲区,而是在有进程访问的时候才会开辟(写时拷贝的思想,提高效率)
(4)独特的打开特性:
命名管道文件以只读打开,则阻塞,直到管道文件被其他进程以写的方式打开;
命名管道文件以只写打开,则阻塞,直到管道文件被其他进程以写的方式打开;
(5)管道总结
本质:内核中的缓冲区
分类:匿名管道/命名管道
匿名管道:仅能用于具有亲缘关系的进程间通信
命名管道:可以用于同一主机上任意进程间通信
操作:
int pipe(int pipefdp[2]);
int mkfifo(char *filename, mode_t mode);
特性:
①半双工通信
②生命周期随进程(在不人为干预的情况,所有打开管道的进程退出,则管道缓冲区被释放)
③管道提供流式传输(以字节为单位的数据先进先出,所有读端关闭write异常,所有写端关闭read返回0不再阻塞)
④管道自带同步与互斥
同步:
操作按照一定秩序进行,
写入数据才能读取数据,
(没有数据则read阻塞;数据满了write阻塞,读取了才能继续写)
互斥:
操作都是安全可靠的。
(如果没有互斥,则两个进程若同时向管道写入数据
则有可能出现交叉写入,数据混乱)
读写大小不超过PIPE_BUF(4096字节)大小则保证原子操作;
原子操作:要么一次完成,要么不做的操作,中间不会被打断。
2. 共享内存
(1)特性
①所有进程间通信方式中最快的一种;
②共享内存周期随内核,在不人为删除的情况, 所有映射进程退出也不会释放共享内存。
(2)速度快
因为通过虚拟地址直接访问内存,相较于其他方式少了两次用户空间与内核空间之间的数据拷贝。
(3)本质原理
开辟一块物理内存,需要进行通信的进程将这块物理内存映射到自己的虚拟地址空间中,直接使用自己的用户空间地址访问。
共享内存是一种覆盖式操作.
(4)操作流程
- 创建或打开共享内存
- 将共享内存映射到虚拟地址空间
- 内存操作(memcpy,printf)
- 解除映射关系
- 删除共享内存(共享内存不会被立即删除,而是等到共享内存的映射连接数为0时才会删除)
(1)创建或打开
int shmget(key_t key, size_t size, int shmflag);
key:共享内存标识符(为了让多个进程找到同一个)
size:需要创建的共享内存大小(仅创建时有效)
shmflag: IPC_CREAT | IPC_EXCL
IPC_CREAT:不存在则创建,存在则打开。
IPC_EXCL与IPC_CREAT搭配使用,
表示存在则报错,不存在则创建打开。
mode: 0664 设置共享内存访问权限
返回值:成功返回一个非负整数-操作句柄;失败返回-1。
(2)建立映射关系
void *shmat(int shm_id, void *shmaddr,int shmflag)
shm_id: shmget返回的操作句柄
shmaddr: 通常置NULL,让系统自动分配建立映射
shmflag: SHM_RDONLY-只读; 0-默认是可读可写
返回值:成功返回映射的首地址;失败返回(void*)-1。
(3)解除映射关系
int shmdt(void *shm_start)
shm_start:映射首地址-shmat的返回值
返回值:成功返回0;失败返回-1。
(4)删除共享内存
int shmctl(int shm_id, int cmd, struct shmid_ds *buf)
shmid:操作句柄
cmd:IPC_RMID -标记删除(不再接受新的映射)
buf:用于获取共享内存信息,用不上就置NULL
返回值:成功返回0; 针对IPC_RMID失败返回-1。
(5)共享内存总结
本质原理: 开辟一块内存空间,多个进程将同一块空间映射到自己的虚拟地址空间进行访问,实现数据共享。
特性:
①最快的进程间通信方式
②生命周期随内核
注意:
①共享内存是一种覆盖式内存操作
②共享内存的操作需要考虑安全问题(没有互斥同步关系)
3.消息队列
(1)本质
内核中创建的一个优先级队列;
具有标识符能被其他进程找到,
多个进程通过访问同一个队列,通过添加或者获取节点实现通信。
消息队列传输的都是数据节点
节点中包含两个信息:
1.类型 2.数据
类型作用:用于身份区分; 优先级
(2)特性
- 半双工通信
- 自带同步互斥
- 生命周期随内核
本次所讲的进程间通信都是systemV标准的,
POSIX标准也有自己的进程间通信方式
4.信号量
(1)本质
内核中的一个计数器
(2)作用
实现进程间的同步与互斥(保护进程间对临界资源的操作)
临界资源:大家都能访问的资源.
(3)如何实现保护操作
同步: 通过一些条件使进程资源的访问更加有序。
互斥: 通过让进程同一时间对资源的唯一访问保证操作安全。
Eg:停车场的计数牌-统计空闲车位,为0则不能停车。
(4)信号量实现同步与互斥原理
通过计数器对资源进行计数:
若计数大于0则表示可以访问资源;
若资源小于0则表示不能访问,则阻塞进程;
其他进程生产一个资源后,计数+1,唤醒一个阻塞进程
操作:
P操作: 在进程访问资源之前进行,判断计数是否大于0
大于0,则正确返回,计数-1;
小于0,则阻塞进程,计数-1;
V操作: 当产生一个新的资源后,计数+1,唤醒一个阻塞进程
(1)实现互斥:
初始化临界资源计数器为1;(表示资源只有1个)
在访问临界资源之前进行P操作;
在访问临界资源之后进行V操作。
(2)实现同步:
根据资源数量初始化计数器,
访问/获取资源之前进行P操作;
产生一个新资源之后进行V操作。
最后
以上就是生动羊为你收集整理的linux下的进程间通信(IPC)一、进程间通信(IPC)是什么?二、四种通信方式的全部内容,希望文章能够帮你解决linux下的进程间通信(IPC)一、进程间通信(IPC)是什么?二、四种通信方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复