文章 https://zhuanlan.zhihu.com/p/165224175 的学习笔记
每个进程的⽤户地址空间都是独立的,⼀般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
管道
【本质】内核里的一串缓存
匿名管道
1 | $ ps auxf | grep mysql |
上⾯命令⾏⾥的「 | 」竖线就是⼀个管道,它的功能是将前⼀个命令( ps auxf )的输出,作为后⼀个命
令( grep mysql )的输⼊
这是匿名管道,用完就被销毁。匿名管道是特殊的文件,存于内存中,而不在文件系统中
命名管道
又叫做FIFO
1 | $ mkfifo myPipe //创建管道 |
底层原理
匿名管道的创建需要通过以下系统调用
1 | int pipe(int fd[2]) |
...
由以上可以得知
匿名管道只能在父子进程之间通信,因为它没有文件实体,只能通过fork来复制父进程fd文件描述符
命名管道由于具有文件实体,可以在不相关进程之间通信
优劣
优点:
- 简单,容易得知管道里的数据被读取
- 通信及时
缺点:
- 效率低(因为通信时进程会被阻塞),不适合进程间频繁地交换数据
消息队列
【本质】内核中的消息链表
A 进程要给 B 进程发送消息,A 进程把数据放入消息队列后就可以正常返回了,B 进程需要时再去读取就可以了
消息队列⽣命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列会⼀直存在
优劣
优点:
- 利于频繁通信
缺点:
- 通信不及时
- 不适合大数据的传输
- 存在用户态和内核态之间的数据拷贝开销
共享内存(最快)
【本质】不同进程的虚拟地址,映射到相同的物理内存中
这样这个进程写⼊的东⻄, 另外⼀个进程⻢上就能看到,不需要拷⻉来拷⻉去(消息队列),大大提⾼了进程间通信的速度。
优劣
优点:
- 速度快
缺点:
- 多个进程共享同一个内存,可能会发生冲突 (并发问题)
信号量
信号量表示资源的数量,控制信号量的⽅式有两种原⼦操作:
- P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占⽤,进程需 阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使⽤,进程可正常继续执⾏
- V 操作,这个操作会把信号量加上 1,**相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行**;相加后如果信号量 > 0,则表明当前没有阻塞中的进程
P 操作是⽤在进⼊共享资源之前,V 操作是⽤在离开共享资源之后,这两个操作是必须成对出现的
根据这个原理,可以推出
- 1 为互斥信号量:保证任意时刻只有一个进程访问共享资源
- 0 为同步信号量:保证A进程一定在B进程之前执行
信号
用于异常下的工作模式,也是唯一的异步通信机制
进程有三种方式响应信号:
- 执行默认操作
- 捕捉信号:为信号定义处理函数
- 忽略信号:
SIGKILL
和SEGSTOP
无法被忽略
Socket
用于跨网络,不同主机之间的通信,但仍可用于同主机的进程通信。
根据创建的socket类型,分为三种通信方式:TCP、UDP、本地进程