0x00 引言
在一个进程运行过程中,通常变量、信号都只能在进程内部传递。当一个进程为多线程的时候,甚至变量、信号也只能在线程内部传递。但是有很多实际场景需要实现进程与进程之间、线程与线程之间实现信息互通,当有这些需求时就涉及到了线程间通信与进程间通信。
0x01 进程、线程与协程
1 | 1 进程 |
1、进程
进程是系统进行资源分配和调度的基本单位。每一个进程都有它自己的地址空间,包括文本区域(存储处理器执行的代码)、数据区域(存储变量和进程执行期间使用的动态分配的内存)和堆栈(存储着活动过程调用的指令和本地变量)。
2、线程
线程是进程的一个实体。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
3、协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。
0x02 进程间通信
1 | 1 管道 |
进程间通信主要有以下六种方法[1]
1、管道
1 | $ ps -ef |grep "xxx" |
类似于上述命令,匿名管道符号’|’就是将ps进程的结果输送给grep进程。管道这种通信方式效率低, 不适合进程间频繁地交换数据。
2、消息队列
消息队列是保存在内核中的消息链表,消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。
实现消息队列推荐使用Boost.InterProcess
3、信号量
为了防止多进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问。正好,信号量就实现了这一保护机制。
信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。可以理解为进程间的锁。
4、共享内存
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。
5、信号
信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身。比如Ctrl + C产生SIGINT信号。
6、套接字
网络通信Socket可用于本机的进程间通信,也可用于不同机器之间的进程间通信。
0x03 线程间通信
1 | 1 volatile |
1、volatile
基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。
1 |
|
2、wait/notify机制
1 |
|