进程间的通信方式
进程间的通信方式
1、管道:其实就是一个进程将数据写到内核中,另一个线程从内核中读取数据。
- 单向:无格式的流并且大小受限;先进先出;管道这种通信方式效率低,不适合进程间频繁地交换数据;
- 匿名管道:匿名管道是只能用于存在父子关系的进程间通信
- 命名管道:可以在任何的进程之间使用,因为使用命名管道的前提,需要在文件系统创建⼀个类型为p的设备文件,那么毫无关系的进程就可以通过这个设备文件进行通信
2、消息队列:消息队列实际上是保存在内核的「消息链表」
- 缺点:消息队列通信的速度不是最及时的,毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程,造成了消耗。
3、共享内存:它直接分配⼀个共享空间,每个进程都可以直接访问。可以解决消息队列通信中⽤户态与内核态之间数据拷贝过程带来的开销。
- 缺点:多进程竞争同个共享资源会造成数据的错乱。
4、信号量:来保护共享资源,以确保任何时刻只能有⼀个进程访问共享资源,这种方式就是互斥访问。信号量不仅可以实现访问的互斥性,还可以实现进程间的同步,信号量其实是⼀个计数器,表示的是资源个数,其值可以通过两个原⼦操作来控制,分别是 P 操作和 V 操作。
5、信号:是进程间通信机制中唯⼀的异步通信机制,信号可以在应⽤进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件。
- 信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)
- ⼀旦有信号发生,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。
- 有两个信号是应用进程无法捕捉和忽略的,即sigkill和segstop,这是为了方便我们能在任何时候结束或止某个进程。
6、Socket:要想跨网络与不同主机上的进程之间通信,就需要 Socket 通信了
CPU上下文切换
1、上下文是谁(切换的是谁):CPU寄存器和程序计数器
2、不同的环境,就需要不同的内核资源,用户资源,线程资源的"保存和恢复"。
内核资源:内核堆栈
用户资源:虚拟内存,全局变量
线程资源:私有数据
3、CPU的上下文切换还分为不同的场景:
- 进程上下文切换:进程是由内核来管理和调度的,进程的切换只能发生在内核态。 所以,进程的上下文不仅包括了用户资源,还有内核资源。
- 线程上下文切换:线程是调度的基本单位,而进程则是资源拥有的基本单位
不同进程下的线程:就跟进程切换一样。
同一进程下的线程:因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程资源就行。
- 中断上下文切换:为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件
中断上下文切换并不涉及到进程的用户态,只需要切换内核资源。
进程终止的方式:
-
正常退出(自愿的):多数进程是由于完成了工作而终止,退出软件。
-
错误退出(自愿的):比如用户操作了一个不存在的文件,于是编译器就会发出声明并退出
-
严重错误(非自愿的):由于程序中的错误所导致的。例如,执行了一条非法指令,引用不存在的内存,或者除数是 0 等
-
被其他进程杀死(非自愿的):某个进程执行系统调用告诉操作系统杀死某个进程。在 UNIX 中,这个系统调用是 kill。在 Win32 中对应的函数是 TerminateProcess