您的位置:首页 > 运维架构 > Nginx

文章3:Nginx中与信号有关的内容

2012-12-30 18:39 381 查看
欢迎转载,转载请注明出处/article/1389067.html

0.序
一概述:
二、启动时,
三、信号初始化
四、启动后的操作
五、几个小问题
0.序
要想学好Nginx中与信号有关的内容,就必须对Linux下信号相当熟悉。因此,在学习Nginx这部分的时候最好重温一下APUE chapter 10 信号。

一概述:
Nginx中使用信号来控制Nginx停止、平滑重启,Nginx支持以下几种信号:
1)TERM,INT快速关闭 SIGINT SIGTERM 即:NGX_TERMINATE_SIGNAL and SIGINT
2)QUIT 从容关闭 SIGQUIT 即 NGX_SHUTDOWN_SIGNAL
3)HUP 平滑重启,重新加载配置文件 SIGHUP 即NGX_RECONFIGURE_SIGNAL
4)USR1 重新打开日志文件,在切割日志时用途较大 SIGUSR1 即NGX_REOPEN_SIGNAL
5)USR2 平滑升级可执行程序 SIGUSR2 即NGX_CHANGEBIN_SIGNAL
6)WINCH 从容关闭工作进程 即NGX_NOACCEPT_SIGNAL
二、启动时,

1.启动时,如果为./nginx -s xxxx则ngx_signal就会获得取值

全局变量ngx_signal获得取值在ngx_get_options函数中获得
if (ngx_signal) {

return ngx_signal_process(cycle, ngx_signal);

}
ngx_signal_process:
首先:从存放pid的文件中读取pid 然后关闭文件
其次:进入ngx_os_signal_process
遍历signal数组,找到匹配的信号并通过kill 杀死进程
三、信号初始化
ngx_init_signals 函数的主要作用:通过sigaction函数设置signal数组中与指定信号相关联的处理动作。
signals数组如下所示:只是列举了一部分

ngx_signal_t signals[] = {

{ ngx_signal_value(NGX_RECONFIGURE_SIGNAL),

"SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),

"reload",

ngx_signal_handler },

............................

{ 0, NULL, "", NULL }

};
关于这部分内容详见1)nginx源码分析—信号初始化

2)参见APUE p261 10.14 sigaction函数

ngx_int_t

ngx_init_signals(ngx_log_t *log)

{

ngx_signal_t *sig;

struct sigaction sa;

for (sig = signals; sig->signo != 0; sig++) {

ngx_memzero(&sa, sizeof(struct sigaction));

sa.sa_handler = sig->handler;

sigemptyset(&sa.sa_mask);

if (sigaction(sig->signo, &sa, NULL) == -1) { /*设定每个SIGXXX的信号处理程序*/

ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,

"sigaction(%s) failed", sig->signame);

return NGX_ERROR;

}

}

return NGX_OK;

}
四、启动后的操作
.启动以后,如果要停止或者平滑重启,命令为$./nginx -s stop / reload
在master进程中的cycle函数ngx_master_process_cycle中
关于这部分内容 要参考APUE p256 10.11 信号集

1)设置信号集set

2) 通过sigsuspend函数等待信号到来,当收到./nginx -s stop 命令时,sigsuspend就会被触发。

sigsuspend(&set);

3)之后向子进程发出相关信号。这部分内容就是master进程与worker进程的通信。
将ngx_master_process_cycle中内容提炼处理

sigemptyset(&set);/*信号集清空,必须操作*/

/*向信号集中添加要阻塞的信号*/

sigaddset(&set, SIGCHLD);

sigaddset(&set, SIGALRM);

sigaddset(&set, SIGIO);

sigaddset(&set, SIGINT);

sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));

sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));

sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));

sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));

sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));

sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));

/*将信号集中的信号添加到信号屏蔽字中*/

sigprocmask(SIG_BLOCK, &set, NULL);

/*清空信号集,供sigsuspend使用*/

sigemptyset(&set);

sigsuspend(&set);/*等到信号到来。当有信号到来时,解除信号的阻塞,进程暂停

在进程暂停过程中会执行信号处理函数,在signals数组中有设置。比如reload其处理函数为ngx_signal_handler 。当执行完信号处理函数ngx_signal_handler后,进程继续运行,继续执行sigsuspend下面的代码*/

接下来master进程将“陷入”死循环中守护着worker进程,担当起伟大的幕后工作。
在master cycle中调用了sigsuspend(),因而将master进程挂起,等待信号的产生
主要过程就是:这些都是标准的信号处理的过程。
【收到信号】,
【调用信号处理函数(在初始化过程中注册了)】,
【设置对应的全局变量】,
【sigsuspend函数返回,判断各个全局变量的值并采取相应的动作】
五、几个小问题:来自于文章 nginx源码分析—信号初始化

5.1ngx_signal_value宏是如何得到整数的信号值signo的?

举个例子,NGX_RECONFIGURE_SIGNAL=HUP,因此ngx_signal_value(NGX_RECONFIGURE_SIGNAL)=SIGHUP。

从上述signals数组可以看出,SIGHUP的signo=1,name为"reload"。那么,这个1是在哪里定义的?

——这很容易能想到kernel源代码。果期不然,在#include <signal.h>
#define SIGHUP 1

#define SIGINT 2

#define SIGQUIT 3

#define SIGILL 4

#define SIGTRAP 5

#define SIGABRT 6

#define SIGIOT 6

#define SIGBUS 7

#define SIGFPE 8

.........................
参考文章:
/article/1451042.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: