笔记目录
1.进程间通信概念 IPC
进程通常需要与其它进程进行协作完成工作任务,他们之间需要通信已到达信息交互的需求,进程的用户空间都是私有的,而内核空间是共享的,所以进程间通信是基于内核的通信技术进行数据传递。
常见的进程间通信技术包括:
- 管道技术
- 消息队列
- 共享内存
- 信号
- 信号量
- socket
2.管道技术
在shell管道中,第一个进程的输出可作为第二个进程参数输入,这样沿着管道命令传递下去。例如在Linux操作系统中ps -aux | grep java
,|
命令符号就是管道。管道的特点是单工读写,也就是说数据传递是单向的,并且管道技术是进程通信手段里效率相对低下的。
2.1 匿名管道 pipe
- 单工通信
- 通信的进程必须是有亲缘关系
- 管道创建时有2个文件描述符,分别指向读管道和写管道
- 生命周期跟随进程
2.2 命名管道 fifo
- `mkfifo`命令创建
- 文件系统可见,存在于内存
- 通信进程无需亲缘关系
- 单工通信
3.消息队列
操作系统在内核维护了一个消息链表结构体,可以达到不同进程间发布和消费不同类型的消息,从而达到进程通信的结果。进程可发布不同类型的数据,数据块将保存在操作系统内核中,等待另外进程的消费,消费完毕内核将删除消息,内核空间没有被回收则未消费的消息一直存在。
但是,消息队列方式进程通信会对数据进行用户空间和内核空间拷贝。
- 消息都带有唯一的消息ID进行标识
- 消息在内核空间维护成一个链表
- 消息可按照不同的类型进行发布和订阅
4. 共享内存
为了解决消息队列这种频繁的内核和用户空间的频繁数据拷贝,操作系统提供了一种机制来实现进程通信,共享内存
;它将一段物理地址共享给不同的进程,已达到不同进程共享同一区域的内存数据从而进行通信,并且共享内存方式的效率很高。
4.1 特点
- 每一个IPC(通信对象)对象都有唯一的key进行标识
- 内存对象不跟随进程的生命周期,创建后如果没有显示删除,它将一直存在
- 共享内存对象在内核空间创建,但是可以被进程映射到自己的虚拟地址用户空间,不需要内核态切换,效率高、灵活。
- 共享内存对象的读写协作需要操作系统提供同步和互斥机制配合完成,否则会出现数据安全问题。
- 共享内存对象有大小限制,默认32m,可通过`SHMMAX`命令配置。
4.2 步骤
- 生成共享内存对象的唯一标识key
- 创建、打开共享内存
- 映射共享内存
- 读写共享内存
- 删除共享内存
4.3 内存映射 mmap
操作系统可通过mmap()函数映射普通文件,使得一个磁盘文件与内存的一块缓冲区相映射,进程可以像操作内存一样读写文件,不需要文件系统提供的read/write。在映射共享内存虚拟页面时并不会立即读入文件数据到内存,而是在访问页面时才会被每一页每一页的读入。当进程退出或显示调用撤销映射时,内存数据会被写回磁盘文件。
今天是大年初五,今天坐车回到成都,明天再玩一天就要上班了,昨天复习的是进程通信里面的管道、消息队列、共享内存,今天继续复习剩下的进程间通信机制。
— Minor 王智
** 2022-02-05**
5.信号灯/信号量
信号量
是E.W.Dijkstra在1965年提出的一种进程/线程传递信号的一种方式,它使用一个整型变量来记录累计唤醒次数,这个信号量取值>=0;
5.1 特点
- 整形数值表示信号值
- P(申请资源)、V(释放资源)是原子操作
5.2 信号量分类
- 有名信号量
- 无名信号量
- System V信号量
6.信号
kill -9 1
就是一种信号机制,在Linux系统中可以使用kill -l
命令查看系统所支持的信号,操作系统提供了非常多的信号种类,每种信号会让进程执行不同的任务。
6.1 特点
- 异步通信
- 不同类型的信号代表不同的事件
6.2 进程响应信号方式
- 缺省
- 忽略信号
- 捕捉信号
6.3 如何产生信号
- 外接I/O设备命令键入
- 系统调用(函数库)
- 硬件异常产生
- 程序运行时错误异常产生
6.4 信号的阻塞
信号阻塞
:某些条件下,进程不需要立即执行信号事件,但是又不立马丢弃事件,而是延后一段时间后再去处理,这种情况可以通过阻塞信号来实现。一般可以通过sigaddset
和sigdelset
相关命令来添加和移除信号集合实现。
7.套接字Socket
如果两个进程在不同的网络环境或者不同主机中,如果希望他们之间进行数据通信,那么操作系统提供了网络技术,通过socket套接字可以实现跨网、跨物理机的不同进程间的通信。