进程管理——进程间通信

进程管理——进程间通信

引言

  • 每个进程的用户地址空间都是独立的,一般而言是不能相互访问的,但内核空间是每个进程都共享的,所以进程间通信必须通过内核。

进程管理——进程间通信

  • Linux内核提供了不少进程间通信的机制,我们来瞧瞧有哪些?

管道(最简单的方式)

  • Linux内核提供了不少进程间通信的方式,其中最简单的方式就是管道,管道分为匿名管道命名管道

匿名管道

  • 顾名思义,它没有名字标识,一种只存在于内存,不存在于文件系统中的特殊文件,shell命令中【ps auxf | grep mysql】的竖线|就是匿名管道,通信的数据是无格式的流,并且大小受限制,通信的方式是单向的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道,再来匿名管道是只能用于存在父子关系的进程间通信,匿名管道的生命周期随着进程创建而建立,随着进程终止而消失。

命名管道

  • 突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为p的设备文件,所以毫无关系的进程就可以通过这个设备文件进行通信。另外,不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时,自然也是从内核中读取,同时通信数据都遵循先进先出原则,不支持lseek之类的文件定位操作。

消息队列

  • 克服了管道通信的数据都是无格式的字节流的问题,消息队列实际上是保存在内核的消息链表,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体,当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。消息队列通信的速度不是最及时的,毕竟每次数据的写入和读出都需要经过用户态和内核态之间的拷贝过程

共享内存(最快的方式)

  • 解决消息队列通信中用户态和内核态之间数据拷贝过程带来的开销。它直接分配一个共享空间,每个进程都可以直接访问,就像访问进程自己的空间一样快捷方便,不需要陷入内核态或者系统调用,大大提高了通信的速率,享有最快的进程间通信方式之名。
  • 但是高校的共享内存通信,带来的新问题,多进程竞争同个共享资源会造成数据的错乱。

信号量

  • 用来保护共享资源,以确保任何时刻只能有一个进程访问共享资源,这种方式就是互斥访问。信号量不仅可以实现访问的互斥性,还可以实现进程间的同步,信号量其实是一个计数器,表示的是资源个数,其值可以通过P操作和V操作这两个原子操作来控制。
  • P操作:这个操作会把信号量减去1,相减后,如果信号量<0,则表明资源已被占用,进程需阻塞等待;如果信号量>=0,则表明还有资源可使用,进程可正常继续执行。
  • V操作:这个操作会把信号量加上1,相加后,如果信号量>0,则表明当前没有阻塞中的进程;如果信号量<=0,则表明当前有阻塞中的进程,会将该进程唤醒运行。

信号

  • 与信号量名字相似,但是功能一点都不一样。
  • 信号是进程间通信机制中唯一的异步通信机制,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令),一旦有信号发生,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP,这是为了方便我们能在任何时候结束或停止某个进程。

套接字Socket通信

  • 解决不同主机的进程间通信。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。

  • 阅读微信公众号【小林coding 小林coding】之后的笔记,深入了解建议去看公众号