0%

六种进程间通信方式

文章 https://zhuanlan.zhihu.com/p/165224175 的学习笔记

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

image-20220211154310200

管道

【本质】内核里的一串缓存

匿名管道

1
$ ps auxf | grep mysql

上⾯命令⾏⾥的「 | 」竖线就是⼀个管道,它的功能是将前⼀个命令( ps auxf )的输出,作为后⼀个命
令( grep mysql )的输⼊

这是匿名管道,用完就被销毁。匿名管道是特殊的文件,存于内存中,而不在文件系统中

命名管道

又叫做FIFO

1
2
3
4
$ mkfifo myPipe //创建管道
$ echo "hello" > myPipe //将数据写进管道
//操作了后,会发现命令执⾏后就停在这了,这是因为只有当管道⾥的数据被读完后,命令才可以正常退出。
$ cat < myPipe //读取

底层原理

匿名管道的创建需要通过以下系统调用

1
int pipe(int fd[2])

.image-20220211160736005.image-20220211160842309.

由以上可以得知

  • 匿名管道只能在父子进程之间通信,因为它没有文件实体,只能通过fork来复制父进程fd文件描述符

  • 命名管道由于具有文件实体,可以在不相关进程之间通信

优劣

优点:

  • 简单,容易得知管道里的数据被读取
  • 通信及时

缺点:

  • 效率低(因为通信时进程会被阻塞),不适合进程间频繁地交换数据

消息队列

【本质】内核中的消息链表

A 进程要给 B 进程发送消息,A 进程把数据放入消息队列后就可以正常返回了,B 进程需要时再去读取就可以了

消息队列⽣命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列会⼀直存在

优劣

优点:

  • 利于频繁通信

缺点:

  • 通信不及时
  • 不适合大数据的传输
  • 存在用户态和内核态之间的数据拷贝开销

共享内存(最快)

【本质】不同进程的虚拟地址,映射到相同的物理内存中

这样这个进程写⼊的东⻄, 另外⼀个进程⻢上就能看到,不需要拷⻉来拷⻉去(消息队列),大大提⾼了进程间通信的速度。

image-20220211163741951

优劣

优点:

  • 速度快

缺点:

  • 多个进程共享同一个内存,可能会发生冲突 (并发问题)

信号量

信号量表示资源的数量,控制信号量的⽅式有两种原⼦操作:

  • P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占⽤,进程需 阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使⽤,进程可正常继续执⾏
  • V 操作,这个操作会把信号量加上 1,**相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行**;相加后如果信号量 > 0,则表明当前没有阻塞中的进程

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

根据这个原理,可以推出

  • 1 为互斥信号量:保证任意时刻只有一个进程访问共享资源
  • 0 为同步信号量:保证A进程一定在B进程之前执行

信号

用于异常下的工作模式,也是唯一的异步通信机制

进程有三种方式响应信号:

  • 执行默认操作
  • 捕捉信号:为信号定义处理函数
  • 忽略信号:SIGKILLSEGSTOP无法被忽略

Socket

用于跨网络,不同主机之间的通信,但仍可用于同主机的进程通信。

根据创建的socket类型,分为三种通信方式:TCP、UDP、本地进程