本文主要是对图解小林阅读后的总结
一、进程间通信前沿
每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。由此需要进程间通信的一些方式
二、进程间通信方式
1. 管道
应该先讲述管道
管道是内核里面的一段缓存,传输数据是单向的。
1.1 匿名管道
包括 Linux命令的 | 的语句就是创建匿名管道,用完就销毁。传输是单向的。
1.2 命名管道
命名管道也叫做FIFO,因为数据是先进先出的传输方式。创建命名管道可以用mkfifo
如果用 ls -l 指令,文件的文件类型为p,则说明是pipe(管道)的意思
1.3 管道缺点
(1)管道传输的数据是无格式的流且大小受限。
(2)只有当管道里的数据被读完后,命令才可以正常退出。通信效率低下
(3)同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。
(4)对于匿名管道,它的通信范围是存在父子关系的进程。对于命名管道则无此限制
2. 消息队列
上面说到管道通信效率低、容量小,不适合线程间频繁交换数据。消息队列就出现了hh,可以对管道的缺点进行相应的改善
消息队列就像是收发邮件一样,发消息就是给消息队列的链表加消息体,读消息就是从消息队列中取出消息体。同样的消息队列也存在收发邮件一样的缺点:一是通信不及时,二是附件也有大小限制。
2.1 消息队列相比管道的改进
(1)管道传输的是无格式的字节流;消息队列传输的是双方定义的消息体
(2)管道容量受限,很小;消息队列容受消息的最大长度和队列的最大长度限制,但较大
2.2 消息队列的缺点
(1)通信不及时
(2)附件大小受限
(3)存在用户态与内核态之间的数据拷贝开销
3. 共享内存
因为消息队列存在用户态与内核态之间的数据拷贝开销,所以自然而然就会出现一种没有这种内核态、用户态切换开销的线程间通信方式——共享内存。共享内存是线程间通信的最快的一种方式。
3.1 共享内存的机制
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。
3.2 共享内存的缺点
(1)不同进程拥有同样的内存空间,自然而然会发生冲突,不利于系统安全
4. 信号量
信号量就是为了解决共享内存的缺点的!信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。信号量只能同步,不能异步哦!
4.1 信号量的操作
(1)P操作,把信号量-1,如果信号量<0,则阻塞等待
(2)V操作,把信号量+1,如果加完信号量<0,则说明有阻塞等待的进程,则唤醒该进程
4.2 信号量初始化
(1)信号量初始化为0,则为同步信号量
(2)信号量初始化为1,则为互斥信号量
5. 信号
上面说的进程间通信方式都是常规工作状态下的工作模式。对于异常情况下的工作模式,就需要用到信号了。信号和信号量是完全不同的两种方式哦。
信号是通知某个事件已经发⽣;唯⼀的异步通信机制;
5.1 信号的处理
(1)执行默认操作;比如kill -9 那就是杀死进程,那就消灭进程呗
(2)捕捉信号;为信号定义一个信号处理函数,发生即执行(可以引到回调函数)
(3)忽略信号;这个是很常见的一种策略,像鸵鸟一样hh,就像发生死锁也会采用这种
6. Socket
像上面提到的所有进程间通信方式都是在同一台主机上的,想跨网络和不同主机进程之间通信,就需要用到Socket
6.1 Socket通信方式
(1)一个是基于 TCP 协议的通信方式
(2)一个是基于 UDP 协议的通信方式
(3)一个是本地进程间通信方式。
6.2 Socket优缺点
(1)优点:任何进程都能通信
(2)缺点:速度慢