前言
在上一小节中,我们看到了nginx是如何使用master进程创建子进程,以及存储子进程的状态,也知道了进程间通信采用的是socketpair机制。接下来我们将重点分析ngx_spawn_process
调用的proc
函数,即worker进程的工作循环。
ngx_worker_process_cycle
proc
是一个函数指针,worker进程对应的是ngx_worker_process_cycle
函数。
worker进程跟master进程一样,也主要是通过信号改变标识位来决定运行逻辑,目前所用的具有实际意义的标识位对应的信号以及意义如下:
信号 | 全局标识位 | 意义 |
---|---|---|
SIGQUIT | ngx_quit | 优雅的关闭进程 |
SIGTERM | ngx_terminate | 强制关闭进程 |
SIGINT | ngx_terminate | 强制关闭进程 |
SIGUSR1 | ngx_reopen | 重新打开所有文件 |
ngx_worker_process_cycle
对应的源码如下:
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
ngx_uint_t i;
ngx_connection_t *c;
ngx_process = NGX_PROCESS_WORKER;
//初始化worker进程
ngx_worker_process_init(cycle, 1);
//设置进程名
ngx_setproctitle("worker process");
//这里可以忽略掉,因为nginx采用的还是多进程单线程模式
#if (NGX_THREADS)
{
ngx_int_t n;
ngx_err_t err;
ngx_core_conf_t *ccf;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ngx_threads_n) {
if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
== NGX_ERROR)
{
/* fatal */
exit(2);
}
err = ngx_thread_key_create(&ngx_core_tls_key);
if (err != 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
ngx_thread_key_create_n " failed");
/* fatal */
exit(2);
}
for (n = 0; n < ngx_threads_n; n++) {
ngx_threads[n].cv = ngx_cond_init(cycle->log);
if (ngx_threads[n].cv == NULL) {
/* fatal */
exit(2);
}
if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
ngx_worker_thread_cycle,
(void *) &ngx_threads[n], cycle->log)
!= 0)
{
/* fatal */
exit(2);
}
}
}
}
#endif
//根据标识位选择不同的操作
for ( ;; ) {
/* 若设置了退出标识位,则退出ngx_worker_process_cycle
* 该标识位仅当ngx_worker_process_cycle退出时使用
* 当ngx_quit被置位后,会将ngx_exiting置位
* ngx_quit被置位后执行的那段代码并没有调用ngx_worker_process_exit函数
* 而是放在这里执行
*/
if (ngx_exiting) {
c = cycle->connections;
//将所有连接的关闭标识位置位
//在退出前需要将所有读事件处理完
for (i = 0; i < cycle->connection_n; i++) {
/* THREAD: lock */
if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i]