进程间通信的困难
因为每个进程之间的地址空间都是相互独立的, 每个进程都有自己独立的虚拟地址空间, 无法跨进程访问另一个进程的地址空间, 所以进程与进程之间的通信就成为一个问题了
进程间通信的方式
管道
管道就是进程通过在内核空间中建立一块缓存来用于进程和进程之间的交互
因为内核空间是所有进程之间共享的, 所以可以通过往内核空间中共享一块地址的方式来读取和写入数据, 以达到进程和进程之间通信的目的效果
共享内存
管道是通过进程访问共有的内核空间的内存来实现信息的交互, 但是管道有通信不及时和附件大小限制的缺点, 所以可以考虑使用共享内存的方式来实现交互
共享内存就是将两个进程的一块相同的虚拟地址映射到相同的物理内存上, 这样进程与进程之间共同读写这块相同的空间, 就可以很方便的进行信息的交互, 同时还没有管道用户态和内核态切换的效率问题
不过共享内存的方式需要应对多进程环境下同时操作数据导致的数据混乱问题, 所以需要加锁来保证同一时间内只能有一个进程来操作共享内存
信号
一种异常情况下的通信方式, 当程序出现异常的时候操作系统就会发送信号给进程, 同时进程对信号进行处理
同时信号也是硬件和软件交互的一种方式, 硬件会发送中断信号通知操作系统执行对应的任务, 以达到软硬件交互的效果
同时信号还是进程中唯一的异步通信机制, 因为信号发送方只需要关注把信号发送给目标进程就好了, 无序关注进程收到信号后的处理
Socket
网络编程的基石, 通过网络来实现两个进程之间的通信, 同时可以跨主机来进行数据交互
最推荐的一种进程交互方式, 因为当多个服务扩大到一定的程度的时候, 单个主机肯定是无法再继续负担这么多服务了, 此时就需要将这多个服务分散到不同的主机上, 不同主机之间是无法通过管道, 共享内存, 信号等方式来进行交互的, 只能通过网络来通信, 所以就需要使用socket
既然最后都是需要使用socket来进行进程间的通信的, 那不如在一开始设计的时候就使用socket来实现进程与进程间的通信, 这样还可以省去后期更改交互方式的成本
socket通信有以下优点
- 传输数据是字节级, 传输的数据可以自定义
- 可以实现不同主机之间的信息交互
缺点
通过网络传输, 需要对传输的数据进行解析, 转化为应用级数据
线程之间的通信
同个进程下的线程之间都是共享进程的资源,只要是共享变量都可以做到线程间通信,⽐如全局变量,所以对于线程间关注的不是通信⽅式,⽽是关注多线程竞争共享资源的问题,信号量也同样可以在线程间实现互斥与同步:
互斥的⽅式,可保证任意时刻只有⼀个线程访问共享资源
同步的⽅式,可保证线程 A 应在线程 B 之前执⾏