进程间通信 | 管道 消息队列 共享内存 信号量 信号 socket

一.为什么需要进程间通信

进程间通信:两个进程之间的数据交互(数据传输,数据共享)

进程间为什么不能直接通信?

因为进程之间具有独立性,每个进程都有自己的虚拟地址空间,访问的都是自己的虚拟地址空间,因此进程间是无法直接通信的,因此需要操作系统提供中间媒介进行通信.

每个进程的用户地址空间是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信可以通过内核.

二.管道

管道的本质:实际上是内核中的一块缓存区,多个进程访问同一个缓冲区实现通信.

管道的分类:匿名管道和命名管道

匿名管道:

#include <unistd.h>

int fd[2];
int pipe(int fd[2]);

//fd[0]: 管道的读端
//fd[1]: 管道的写端

 

  1. 半双工(数据只能在一个方向上流动),具有固定的读端和写端,需要双方通信时,需要建立起两个管道
  2. 只能用于具有亲缘关系的进程之间的通信(可以是父子进程,也可以是兄弟进程)
  3. 管道基于字节流来通信
  4. 管道的生命周期随进程
  5. 内核对管道操作进行同步与互斥

命名管道:

#include <sys/stat.h>

int mkfifo(const char* path,mode_t mod);
  1. FIFO可以在无关的进程之间交换数据
  2. FIFO有路径名与之相关联,以一种特殊设备文件形式存在于文件系统中

三.消息队列

消息队列是保存在内核中的消息链表.在发送数据时,会分成一个一个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型,所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。

  1. 自带同步与互斥
  2. 生命周期随内核
  3. 消息队列可以实现消息的随机查询,消息不一定要先进先出的次序读取,也可以按照消息的类型读取

消息队列不适合比较大数据的传输,因为在内核中每个消息体都有一个最大长度的限制,同时所有队列所包含的全部消息体的总长度也是有上限。在 Linux 内核中,会有两个宏定义 MSGMAX 和 MSGMNB,它们以字节为单位,分别定义了一条消息的最大长度和一个队列的最大长度。

消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销,因为进程写入数据到内核中的消息队列时,会发生从用户态拷贝数据到内核态的过程,同理另一进程读取内核中的消息队列时,会发生从内核态拷贝数据到用户态的过程.(两次数据拷贝)

四.共享内存

即在物理内存上开辟一块空间,然后多个进程通过页表将这同一个物理内存映射到自己的虚拟地址空间中,通过自己的虚拟地址空间来访问这块物理内存,达到了数据共享的目的.

  1. 共享内存是最快的IPC,因为进程是直接对内存进程存取
  2. 因为多个进程可以同时操作,所以需要同步
  3. 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问

五.信号量

使用共享内存的通信方式存在的问题: 如果多个进程同时修改一个共享内存,很有可能就会发生冲突.

为了防止多进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源在同一时候只能被一个进程访问.因此,引出了信号量实现这一保护机制.

信号量其实是一个整形的计数器,主要用于实现进程间的同步与互斥,而不是用于缓存进程间通信的数据.

  1. 信号量用于进程间同步与互斥,若要在进程间传输数据需要结合共享内存
  2. 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作
  3. 每次对信号量的PV操作不仅限于信号量值加一减一,而且可以加减任意整数

信号量表示资源的数量,控制信号量的方式有两种原子操作

  • 一个是 P 操作,这个操作会把信号量减一,相减后如果信号量 < 0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使用,进程可正常继续执行。

  • 另一个是 V 操作,这个操作会把信号量加一,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程;

  • P 操作是用在进入共享资源之前,V 操作是用在离开共享资源之后,这两个操作是必须成对出现的。

信号量初始化为1,就代表着互斥信号量.可以保证共享内存在任何时刻只有一个进程在访问.

信号量初始化为0,则代表是同步信号量.可以保证进程按照某种规则时序推进执行.

六.信号

对于异常情况下的工作模式,就需要用信号的方式来通知进程.

信号是进程间通信机制中唯一的异步通信机制,可以在任意时刻发送信号给某一进程.

进程对信号的几种处理方式:

  1. 执行默认操作
  2. 捕捉信号
  3. 忽略信号

七.socket套接字

可用于不同主机之间的进程进行通信,也可用于同主机之间的进程进行通信.

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值