1.进程间通信的方式
文件,管道,信号、信号量,共享映射区(共享内存),消息队列,管道,套接字(socket)
着重讲下:
- 管道(使用简单)
- 信号(开销比较小)
- 共享映射区
- 套接字(低速稳定)
一般都是通过内核共享空间进行通信
2.管道(pipe)
- 无名管道,半双工的通信方式(数据流向固定:只能 a 的数据写给 b ,或者 b 的数据写给 a )
- 管道大家可以简单的理解为一种特殊的文件形式,我们可以用文件的读写方法,不是一种简单的文件,只会占用内存。
- 管道只能是有血缘关系的进程间通信
- 数据不能自己写自己读
- 数据一旦读走,不能再次读
1 |
|
非法操作:
读管道:
1.1 管道中有数据,read 返回实际读到的数据1.2 管道中无数据:
1.2.1 管道写端被关闭,read 返回 0 1.2.2 管道写端如果没有被关闭,会阻塞等待
写管道:
2.1 读端被关闭,异常终止(信号导致)2.2 读端未关闭:
2.2.1 管道数据已满,阻塞等待写入数据(其他人读走) 2.2.2 管道未满,直接将数据写入
3.共享映射区
binder 驱动,腾讯 MMKV,xlog (日志库)中都会有 mmap
函数
以下是binder驱动的流程
1 | 1、注册建立ServiceManager表。 |
mmap 注意事项
- 指定映射区的大小,必须要小于文件大小
- 映射区大小必须要大于 0 ,否则会异常
- 创建映射区需要 read 权限,mmap 的读写权限应该 <= 文件的权限
- 文件可以先关闭
- 偏移量必须是 4k 的整数倍
- MAP_PRIVATE 只会对内存进行修改,不会反应到磁盘上
mmap 万能调用方法:
open(O_RDWR);
mmap(NULL, 有效大小,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)
1 |
|
还有示例请可以看这儿
4.信号
进程间通信的机制,内核自带的,信号不能携带大量的数据,一般就是一个数字,只有在特定场景下才调用。
怎样才会产生信号:
- 按键产生: ctrl + c, ctrl+z
- 系统调用 kill , raise, abort
- 软件条件产生, alarm
- 硬件异常产生,非法访问内存,除 0 ,内存对齐等等
- 命令产生
信号的处理方式:
- 忽略此信号
- 执行系统默认动作
- 捕捉用户希望动作
信号处理的原理:
- 信号屏蔽字: 用于屏蔽x信号,内部实现就是一个集合,当 x 信号屏蔽后,再收到该信号,信号处理将推后
- 未决信号集: 信号抵达 x 信号位反转为 1 , 当信号被处理后重新置为 0
man 7 signal
1 | Signal Value Action Comment |
Process.killProcess(Process.myPid());
kill pid (发送信号)
: 第一个参数,,< 0 往 |pid| 发个信息,0 杀死进程组,不要传 -1
- pid > 0 往 pid 进程发个信号
- pid < 0 往 |pid| 发个信息
- pid = 0 杀死进程组
- 不要传 -1 ,会杀死所有能杀死的进程