进程间通信(5):消息队列和信号
消息队列
消息队列(Message Queue)用于在进程之间传递较小的数据,进程可以向一个或多个消息队列中放入数据(消息),其它进程可以从消息队列中按照各种方式(例如最典型的先进先出FIFO方式)取出消息,从而实现进程间通信。
消息队列是一种生产者消费者模型,生产者生产消息放入队列,等待被消费者消费走。如果消息队列已满,生产者被阻塞,如果队列已空,消费者被阻塞。当然,按照不同设计方式,可能会以通知的方式替代阻塞行为。
在分布式系统中,也常使用消息队列模型(如RabbitMQ、Kafka)在多个服务程序之间异步地传递消息。
信号
在现实生活中,红绿灯就是非常常见的信号灯,人在收到红绿灯代表的信号后,就会做出对应的处理:红灯停、绿灯行、黄灯亮了等一等。
Linux也支持信号(signal)机制,它提供了一种软中断机制,可以由于用户程序去决定何时产生中断。例如,用户可以在命令行下随时按下Ctrl+C键来终止正在运行的前台进程,按下Ctrl+C的内部其实发送了一个称为SIGINT的信号给前台进程
Linux中的绝大多数信号都是由内核发送的,所以在发送信号给某进程之前,需要先陷入内核。
Linux中定义了很多信号类型,这些信号都有默认的处理方式(例如红灯亮的信号,人的默认处理方式是停下),但程序内也可以自定义信号的处理方式(例如,红灯亮了偏不停)。当内核将相关信号发送给进程,该进程接收到这些信号后,会触发对应的信号处理程序去处理该信号,从而打断该进程的正常执行流程。
在shell中,也支持信号机制,可通过kill命令发送信号给指定进程。可能这里会出现一个疑惑,刚才说信号绝大多数是由内核发送的,为什么kill命令(bash下有两个kill命令,一个是bash内置kill命令,一个是外置kill命令,但无论如何,都是用户进程)对应的进程能够发送信号给其它进程?这是因为kill发送的信号先是传递给内核的,内核再将这个信号传递给对应进程。所以这里需要进行一次上下文切换。