最近和 Nginx 杠上了( 三 )


如图4所示 , 这个函数主要进行如下操作:
设置进程的初始信号掩码 , 屏蔽相关信号 。 Master进程fork出Worker、CacheManager以及CacheLoader等子进程 。 进入主循环 , 通过sigsuspend系统调用 , 等待着信号的到来 。 一旦信号到来 , 会进入信号处理程序ngx_signal_handler 。 信号处理程序执行之后 , 程序执行流程会判断各种状态位 , 来执行不同的操作 。上面的流程中提到了几个概念 , 这里对其进行说明 , 以便我们更好的理解Master进程的执行过程 。
①信号:用来完成进程中信息传递的媒介 。 Master进程的主循环里面 , 一直通过等待各种信号事件 , 来处理不同的指令 。
这个信号可以传递给Master进程 , 也可以从Master进程传递给其他的进程 。
信号分为标准信号和实时信号 , 标准信号是从1-31 , 实时信号是从32-64 。 例如:INT、QUIT、KILL就是标准信号 。 Master进程监听的信号也是标准信号 。
标准信号和实时信号的区别是:标准信号 , 是基于位的标记 , 假设在阻塞等待的时候 , 多个相同的信号到来 , 最终解除阻塞时 , 只会传递一次信号 , 无法统计等待期间信号的计数 。
而实时信号是通过队列来实现 , 在阻塞等待的时候 , 多个相同的实时信号会存放到队列中 。 一旦解除阻塞的时候 , 会将队列中的信号都进行传递 , 结果会收到多次信号 。
②信号处理器:信号处理器是指当捕获指定信号时(传递给进程)时将会调用的一个函数 , 它存在与进程中 , 它可以随时打断进程的主程序流程 。
③发送信号:发送信号的操作可以使用kill这个shell命令完成 。 比如kill-9pid , 就是发送KILL信号 。
kill-INTpid就是发送INT信号 。 与shell命令类似 , 可以使用kill系统调用来向进程发送信号 。
④信号掩码:用来控制信号阻赛的编码方式 。 每个进程都有一个信号掩码(signalmask) , 也称为信号屏蔽字 , 它规定了当前要屏蔽或要阻塞递送到该进程的信号集 。
对于每种可能的信号 , 该掩码中都有一位与之对应 。 对于某种信号 , 若其对应位(bit)已设置 , 则它当前是被阻塞的 。
简单地说 , 信号掩码是一个“位图” , 其中每一位都对应着一种信号 。 如果位图中的某一位为1 , 就表示在执行当前信号集的处理程序期间相应的信号暂时被“屏蔽”或“阻塞” , 使得在执行的过程中不会嵌套地响应那个信号 。
说白了就是使用信号编码来阻赛信号 , 告诉其他发送信号的进程说:“我在忙着处理事情 , 你先等等 , 等会我再处理你的信号 。 ”
进程之间的信号发送方式
有了上面的基础以后再回头看看Nginx中进程中是如何进行信息交互的 , 以及Master是如何通过信号与Worker进行沟通的 。
最近和 Nginx 杠上了
文章图片
图5:Master与Worker通信
从图5中可以看出 , Master可以接受TERM , INT、QUIT、HUP、USR1、USR2、WINCH这些信号 , 这些信号的含义会在后面提供一张表给大家解释 。
同时Master进程也可以给Worker进程传递信号 , 于是Worker进程可以接收以下信号:TERM , INT、QUIT、HUP、USR1、WINCH 。 之后Worker再去响应Client的请求 。
这里先将信号的对应的命令和含义通过表格的方式列出来 , 再来对其进行讲解 。
最近和 Nginx 杠上了
文章图片
从表格上面看 , 每个信号都有特定的含义 。 比如QUIT信号表示优雅地关闭服务 , 并且对应quit命令 。
这里的quit命令指的是可以通过命令行的方式对Master进程下命令 , 从而达到发送信号的效果 , 当然Master接受到命令以后会转化为信号发送给对应的Worker达到关闭服务的效果 。