第14章 进程间的通信机制

本章并不是说明Linux下有哪些进程通信方式,而是为了说明Nginx选择了哪些方式来同步master进程和多个worker进程间的数据,Nginx框架是怎样重新封装了这些进程间通信方式的,以及在开发Nginx模块时应该怎样使用这些封装过的方法。

Nginx由一个master进程和多个worker进程组成,但master进程或者worker进程中并不会再创建线程(Nginx的多线程机制一直停留在测试状态,虽然不排除未来Nginx可能发布支持多线程版本的可能性,但直到目前最新的1.2.x版本仍然未支持多线程),因此,本章的内容不会涉及线程间的通信。

14.1 概述

Linux提供了多种进程间传递消息的方式,如共享内存、套接字、管道、消息队列、信号等,每种方式都有其优缺点,而Nginx框架使用了3种传递消息传递方式:共享内存、套接字、信号。在14.2节将会介绍Nginx是怎样使用、封装共享内存的;在14.4节会介绍进程间怎样使用套接字通信,以及如何使用基于套接字封装的Nginx频道;在14.5节中将会介绍进程间怎样通过发送、接收信号来传递消息。

在多个进程访问共享资源时,还需要提供一种机制使各个进程有序、安全地访问资源,避免并发访问带来的未知结果。Nginx主要使用了3种同步方式:原子操作、信号量、文件锁。在14.3节将会介绍在Nginx中原子操作是怎样实现的,同时还会介绍基于原子变量实现的自旋锁;在14.6节将会介绍信号量,与“信号”不同的是,中文译名仅有一字之差的“信号量”其实是用于同步代码段的执行的;在14.7节将会介绍文件锁。

由于Nginx的每个worker进程都会同时处理千万个请求,所以处理任何一个请求时都不应该阻塞当前进程处理后续的其他请求。例如,不要随意地使用信号量互斥锁,这会使得worker进程在得不到锁时进入睡眠状态,从而导致这个worker进程上的其他请求被“饿死”。鉴于此,Nginx使用原子操作、信号量和文件锁实现了一套ngx_shmtx_t互斥锁,当操作系统支持原子操作时ngx_shmtx_t就由原子变量实现,否则将由文件锁来实现。顾名思义,ngx_shmtx_t锁是可以在共享内存上使用的,它是Nginx中最常见的锁。