码迷,mamicode.com
首页 > 系统相关 > 详细

菜鸟nginx源码剖析架构篇(二) nginx进程模型

时间:2014-11-18 13:32:09      阅读:456      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   color   ar   os   sp   

菜鸟nginx源码剖析架构篇(二) nginx进程模型

 

  • Author:Echo Chen(陈斌)

  • Email:chenb19870707@gmail.com

  • Blog:Blog.csdn.net/chen19870707

  • Date:Nov 17th, 2014

     

    1.nginx进程模型

    nginx采用的是多进程模型,典型的master-worker方式,采用一个master process(监控进程,也叫做主进程)和多个woker process(工作进程)的设计方式,此外,还有1个可选的chache manager和 1 个可选的cache loader进程。

    bubuko.com,布布扣

    这样设计的好处:
    • (1)利用多核系统的并发处理能力;

    • (2)负载均衡;

    • (3)管理进程会负责监控工作进程的状态,并负责管理其行为。

     

    2. master-worker 启动流程

    启动nginx的主进程将充当master进程,而由主进程fork()出来的子进程则充当工作进程。nginx也可以单进程模型执行,在这种进程模型下,主进程就是工作进程,没有监控进程。

    Nginx的核心进程模型框图如下:

  • bubuko.com,布布扣

    3.master进程是如何工作的

     
    监控进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
    其工作流程如下图,它首先fork出worker进程,然后进入for循环,在每一帧循环中调用sigsupend挂起等待信号,如果收到信号,就处理信号,改变响应的标志位,然后根据标志位做出相应的操作。

    bubuko.com,布布扣

     

    master进程的标志位有如下7个:

       1: sig_atomic_t ngx_reap;
       2: sig_atomic_t ngx_terminate;
       3: sig_atomic_t ngx_quit;
       4: sig_atomic_t ngx_reconfigure;
       5: sig_atomic_t ngx_reopen;
       6: sig_atomic_t ngx_change_binary;
       7: sig_atomic_t ngx_noaccept;
     
    每个标志与信号位的及作用的对应关系如下表:
    bubuko.com,布布扣

    这样,master进程的运行情况如下图:

    bubuko.com,布布扣

    下面看一下核心代码:

    3.1 master进程住循环函数 ngx_master_process_cycle

       1: void
       2: ngx_master_process_cycle(ngx_cycle_t *cycle)
       3: {
       4:     char              *title;
       5:     u_char            *p;
       6:     size_t             size;
       7:     ngx_int_t          i;
       8:     ngx_uint_t         n, sigio;
       9:     sigset_t           set;
      10:     struct itimerval   itv;
      11:     ngx_uint_t         live;
      12:     ngx_msec_t         delay;
      13:     ngx_listening_t   *ls;
      14:     ngx_core_conf_t   *ccf;
      15:  
      16:     //设置屏蔽信号
      17:     sigemptyset(&set);
      18:     sigaddset(&set, SIGCHLD);
      19:     sigaddset(&set, SIGALRM);
      20:     sigaddset(&set, SIGIO);
      21:     sigaddset(&set, SIGINT);
      22:     sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
      23:     sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
      24:     sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
      25:     sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
      26:     sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
      27:     sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
      28:  
      29:     if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
      30:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      31:                       "sigprocmask() failed");
      32:     }
      33:  
      34:     sigemptyset(&set);
      35:  
      36:  
      37:     size = sizeof(master_process);
      38:  
      39:     for (i = 0; i < ngx_argc; i++) {
      40:         size += ngx_strlen(ngx_argv[i]) + 1;
      41:     }
      42:  
      43:     title = ngx_pnalloc(cycle->pool, size);
      44:  
      45:     p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
      46:     for (i = 0; i < ngx_argc; i++) {
      47:         *p++ = ‘ ‘;
      48:         p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
      49:     }
      50:  
      51:     ngx_setproctitle(title);
      52:  
      53:  
      54:     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
      55:  
      56:     //其中包含了fork产生子进程的内容
      57:     ngx_start_worker_processes(cycle, ccf->worker_processes,
      58:                                NGX_PROCESS_RESPAWN);
      59:     //Cache管理进程与cache加载进程的主流程
      60:     ngx_start_cache_manager_processes(cycle, 0);
      61:  
      62:     ngx_new_binary = 0;
      63:     delay = 0;
      64:     sigio = 0;
      65:     live = 1;
      66:  
      67:     for ( ;; ) {//循环
      68:         if (delay) {
      69:             if (ngx_sigalrm) {
      70:                 sigio = 0;
      71:                 delay *= 2;
      72:                 ngx_sigalrm = 0;
      73:             }
      74:  
      75:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
      76:                            "termination cycle: %d", delay);
      77:  
      78:             itv.it_interval.tv_sec = 0;
      79:             itv.it_interval.tv_usec = 0;
      80:             itv.it_value.tv_sec = delay / 1000;
      81:             itv.it_value.tv_usec = (delay % 1000 ) * 1000;
      82:  
      83:             if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
      84:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      85:                               "setitimer() failed");
      86:             }
      87:         }
      88:  
      89:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
      90:  
      91:         sigsuspend(&set);//master进程休眠,等待接受信号被激活
      92:  
      93:         ngx_time_update();
      94:  
      95:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
      96:                        "wake up, sigio %i", sigio);
      97:  
      98:         //标志位为1表示需要监控所有子进程
      99:         if (ngx_reap) {
     100:             ngx_reap = 0;
     101:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
     102:  
     103:             live = ngx_reap_children(cycle);//管理子进程
     104:         }
     105:  
     106:         //当live标志位为0(表示所有子进程已经退出)、ngx_terminate标志位为1或者ngx_quit标志位为1表示要退出master进程
     107:         if (!live && (ngx_terminate || ngx_quit)) {
     108:             ngx_master_process_exit(cycle);//退出master进程
     109:         }
     110:  
     111:         //ngx_terminate标志位为1,强制关闭服务,发送TERM信号到所有子进程
     112:         if (ngx_terminate) {
     113:             if (delay == 0) {
     114:                 delay = 50;
     115:             }
     116:  
     117:             if (sigio) {
     118:                 sigio--;
     119:                 continue;
     120:             }
     121:  
     122:             sigio = ccf->worker_processes + 2 /* cache processes */;
     123:  
     124:             if (delay > 1000) {
     125:                 ngx_signal_worker_processes(cycle, SIGKILL);
     126:             } else {
     127:                 ngx_signal_worker_processes(cycle,
     128:                                        ngx_signal_value(NGX_TERMINATE_SIGNAL));
     129:             }
     130:  
     131:             continue;
     132:         }
     133:  
     134:         //ngx_quit标志位为1,优雅的关闭服务
     135:         if (ngx_quit) {
     136:             ngx_signal_worker_processes(cycle,
     137:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));//向所有子进程发送quit信号
     138:  
     139:             ls = cycle->listening.elts;
     140:             for (n = 0; n < cycle->listening.nelts; n++) {//关闭监听端口
     141:                 if (ngx_close_socket(ls[n].fd) == -1) {
     142:                     ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
     143:                                   ngx_close_socket_n " %V failed",
     144:                                   &ls[n].addr_text);
     145:                 }
     146:             }
     147:             cycle->listening.nelts = 0;
     148:  
     149:             continue;
     150:         }
     151:  
     152:         //ngx_reconfigure标志位为1,重新读取配置文件
     153:         //nginx不会让原来的worker子进程再重新读取配置文件,其策略是重新初始化ngx_cycle_t结构体,用它来读取新的额配置文件
     154:         //再创建新的额worker子进程,销毁旧的worker子进程
     155:         if (ngx_reconfigure) {
     156:             ngx_reconfigure = 0;
     157:  
     158:             //ngx_new_binary标志位为1,平滑升级Nginx
     159:             if (ngx_new_binary) {
     160:                 ngx_start_worker_processes(cycle, ccf->worker_processes,
     161:                                            NGX_PROCESS_RESPAWN);
     162:                 ngx_start_cache_manager_processes(cycle, 0);
     163:                 ngx_noaccepting = 0;
     164:  
     165:                 continue;
     166:             }
     167:  
     168:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
     169:  
     170:             //初始化ngx_cycle_t结构体
     171:             cycle = ngx_init_cycle(cycle);
     172:             if (cycle == NULL) {
     173:                 cycle = (ngx_cycle_t *) ngx_cycle;
     174:                 continue;
     175:             }
     176:  
     177:             ngx_cycle = cycle;
     178:             ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
     179:                                                    ngx_core_module);
     180:             //创建新的worker子进程
     181:             ngx_start_worker_processes(cycle, ccf->worker_processes,
     182:                                        NGX_PROCESS_JUST_RESPAWN);
     183:             ngx_start_cache_manager_processes(cycle, 1);
     184:  
     185:             /* allow new processes to start */
     186:             ngx_msleep(100);
     187:  
     188:             live = 1;
     189:             //向所有子进程发送QUIT信号
     190:             ngx_signal_worker_processes(cycle,
     191:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
     192:         }
     193:         //ngx_restart标志位在ngx_noaccepting(表示正在停止接受新的连接)为1的时候被设置为1.
     194:         //重启子进程
     195:         if (ngx_restart) {
     196:             ngx_restart = 0;
     197:             ngx_start_worker_processes(cycle, ccf->worker_processes,
     198:                                        NGX_PROCESS_RESPAWN);
     199:             ngx_start_cache_manager_processes(cycle, 0);
     200:             live = 1;
     201:         }
     202:  
     203:         //ngx_reopen标志位为1,重新打开所有文件
     204:         if (ngx_reopen) {
     205:             ngx_reopen = 0;
     206:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
     207:             ngx_reopen_files(cycle, ccf->user);
     208:             ngx_signal_worker_processes(cycle,
     209:                                         ngx_signal_value(NGX_REOPEN_SIGNAL));
     210:         }
     211:  
     212:         //平滑升级Nginx
     213:         if (ngx_change_binary) {
     214:             ngx_change_binary = 0;
     215:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
     216:             ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
     217:         }
     218:  
     219:         //ngx_noaccept为1,表示所有子进程不再处理新的连接
     220:         if (ngx_noaccept) {
     221:             ngx_noaccept = 0;
     222:             ngx_noaccepting = 1;
     223:             ngx_signal_worker_processes(cycle,
     224:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
     225:         }
     226:     }
     227: }

     

    3.2 master 产生master进程函数 ngx_start_worker_processes

       1: static void
       2: ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
       3: {
       4:     ngx_int_t      i;
       5:     ngx_channel_t  ch;
       6:  
       7:     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
       8:  
       9:     ch.command = NGX_CMD_OPEN_CHANNEL;
      10:  
      11:     //循环创建n个worker子进程
      12:     for (i = 0; i < n; i++) {
      13:         //完成fok新进程的具体工作
      14:         ngx_spawn_process(cycle, ngx_worker_process_cycle,
      15:                           (void *) (intptr_t) i, "worker process", type);
      16:  
      17:         //全局数组ngx_processes就是用来存储每个子进程的相关信息,如:pid,channel,进程做具体事情的接口指针等等,这些信息就是用结构体ngx_process_t来描述的。
      18:         ch.pid = ngx_processes[ngx_process_slot].pid;
      19:         ch.slot = ngx_process_slot;
      20:         ch.fd = ngx_processes[ngx_process_slot].channel[0];
      21:  
      22:         /*在ngx_spawn_process创建好一个worker进程返回后,master进程就将worker进程的pid、worker进程在ngx_processes数组中的位置及channel[0]传递给前面已经创建好的worker进程,然后继续循环开始创建下一个worker进程。刚提到一个channel[0],这里简单说明一下:channel就是一个能够存储2个整型元素的数组而已,这个channel数组就是用于socketpair函数创建一个进程间通道之用的。master和worker进程以及worker进程之间都可以通过这样的一个通道进行通信,这个通道就是在ngx_spawn_process函数中fork之前调用socketpair创建的。*/
      23:         ngx_pass_open_channel(cycle, &ch);
      24:     }
      25: }

    3.3 真正的fork函数 ngx_spawn_process

       1: //参数解释:
       2: //cycle:nginx框架所围绕的核心结构体
       3: //proc:子进程中将要执行的工作循环
       4: //data:参数
       5: //name:子进程名字
       6: ngx_pid_t
       7: ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
       8:     char *name, ngx_int_t respawn)
       9: {
      10:     u_long     on;
      11:     ngx_pid_t  pid;
      12:     ngx_int_t  s;
      13:  
      14:     if (respawn >= 0) {
      15:         s = respawn;
      16:  
      17:     } else {
      18:         for (s = 0; s < ngx_last_process; s++) {
      19:             if (ngx_processes[s].pid == -1) {
      20:                 break;
      21:             }
      22:         }
      23:  
      24:         if (s == NGX_MAX_PROCESSES) {
      25:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
      26:                           "no more than %d processes can be spawned",
      27:                           NGX_MAX_PROCESSES);
      28:             return NGX_INVALID_PID;
      29:         }
      30:     }
      31:  
      32:  
      33:     if (respawn != NGX_PROCESS_DETACHED) {
      34:  
      35:         /* Solaris 9 still has no AF_LOCAL */
      36:         //创建父子进程间通信的套接字对(基于TCP)
      37:         if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
      38:         {
      39:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      40:                           "socketpair() failed while spawning \"%s\"", name);
      41:             return NGX_INVALID_PID;
      42:         }
      43:  
      44:         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
      45:                        "channel %d:%d",
      46:                        ngx_processes[s].channel[0],
      47:                        ngx_processes[s].channel[1]);
      48:  
      49:         //设置为非阻塞模式
      50:         if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
      51:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      52:                           ngx_nonblocking_n " failed while spawning \"%s\"",
      53:                           name);
      54:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      55:             return NGX_INVALID_PID;
      56:         }
      57:  
      58:         if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
      59:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      60:                           ngx_nonblocking_n " failed while spawning \"%s\"",
      61:                           name);
      62:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      63:             return NGX_INVALID_PID;
      64:         }
      65:  
      66:         on = 1;
      67:         if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
      68:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      69:                           "ioctl(FIOASYNC) failed while spawning \"%s\"", name);
      70:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      71:             return NGX_INVALID_PID;
      72:         }
      73:  
      74:         if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
      75:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      76:                           "fcntl(F_SETOWN) failed while spawning \"%s\"", name);
      77:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      78:             return NGX_INVALID_PID;
      79:         }
      80:  
      81:         if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
      82:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      83:                           "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
      84:                            name);
      85:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      86:             return NGX_INVALID_PID;
      87:         }
      88:  
      89:         if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
      90:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      91:                           "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
      92:                            name);
      93:             ngx_close_channel(ngx_processes[s].channel, cycle->log);
      94:             return NGX_INVALID_PID;
      95:         }
      96:  
      97:         ngx_channel = ngx_processes[s].channel[1];
      98:  
      99:     } else {
     100:         ngx_processes[s].channel[0] = -1;
     101:         ngx_processes[s].channel[1] = -1;
     102:     }
     103:  
     104:     ngx_process_slot = s;
     105:  
     106:     //创建子进程
     107:     pid = fork();
     108:  
     109:     switch (pid) {
     110:  
     111:     case -1:
     112:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
     113:                       "fork() failed while spawning \"%s\"", name);
     114:         ngx_close_channel(ngx_processes[s].channel, cycle->log);
     115:         return NGX_INVALID_PID;
     116:  
     117:     case 0:
     118:         ngx_pid = ngx_getpid();
     119:         proc(cycle, data);
     120:         break;
     121:  
     122:     default:
     123:         break;
     124:     }
     125:  
     126:     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);
     127:  
     128:     ngx_processes[s].pid = pid;
     129:     ngx_processes[s].exited = 0;
     130:  
     131:     if (respawn >= 0) {
     132:         return pid;
     133:     }
     134:  
     135:     ngx_processes[s].proc = proc;
     136:     ngx_processes[s].data = data;
     137:     ngx_processes[s].name = name;
     138:     ngx_processes[s].exiting = 0;
     139:  
     140:     switch (respawn) {
     141:  
     142:     case NGX_PROCESS_NORESPAWN:
     143:         ngx_processes[s].respawn = 0;
     144:         ngx_processes[s].just_spawn = 0;
     145:         ngx_processes[s].detached = 0;
     146:         break;
     147:  
     148:     case NGX_PROCESS_JUST_SPAWN:
     149:         ngx_processes[s].respawn = 0;
     150:         ngx_processes[s].just_spawn = 1;
     151:         ngx_processes[s].detached = 0;
     152:         break;
     153:  
     154:     case NGX_PROCESS_RESPAWN:
     155:         ngx_processes[s].respawn = 1;
     156:         ngx_processes[s].just_spawn = 0;
     157:         ngx_processes[s].detached = 0;
     158:         break;
     159:  
     160:     case NGX_PROCESS_JUST_RESPAWN:
     161:         ngx_processes[s].respawn = 1;
     162:         ngx_processes[s].just_spawn = 1;
     163:         ngx_processes[s].detached = 0;
     164:         break;
     165:  
     166:     case NGX_PROCESS_DETACHED:
     167:         ngx_processes[s].respawn = 0;
     168:         ngx_processes[s].just_spawn = 0;
     169:         ngx_processes[s].detached = 1;
     170:         break;
     171:     }
     172:  
     173:     if (s == ngx_last_process) {
     174:         ngx_last_process++;
     175:     }
     176:  
     177:     return pid;
     178: }

     

    4.worker 进程是如何工作的

    worker进程的主要任务是完成具体的任务逻辑。其主要关注点是与客户端或后端真实服务器(此时nginx作为中间代理)之间的数据可读/可写等I/O交互事件,所以工作进程的阻塞点是在像select()、epoll_wait()等这样的I/O多路复用函数调用处,以等待发生数据可读/写事件。当然也可能被新收到的进程信号中断。

    master进程是信号来控制worker进程的。当收到信号时,信号处理函数ngx_signal_handler()就会执行。worker进程感兴趣的信号有4个,也是通过4个变量来控制,如下表:

    bubuko.com,布布扣

    其工作流程如下图所示:

    bubuko.com,布布扣

    其核心代码如下:

       1: static void
       2: ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
       3: {
       4:     ngx_int_t worker = (intptr_t) data;
       5:  
       6:     ngx_uint_t         i;
       7:     ngx_connection_t  *c;
       8:  
       9:     ngx_process = NGX_PROCESS_WORKER;
      10:  
      11:     //子进程初始化
      12:     ngx_worker_process_init(cycle, worker);
      13:  
      14:     ngx_setproctitle("worker process");
      15:  
      16: //这里有一段多线程条件下的代码。由于nginx并不支持多线程,因此删除掉了
      17:  
      18:     //循环
      19:     for ( ;; ) {
      20:         
      21:         //ngx_exiting标志位为1,进程退出
      22:         if (ngx_exiting) {
      23:             c = cycle->connections;
      24:             for (i = 0; i < cycle->connection_n; i++) {
      25:                 if (c[i].fd != -1 && c[i].idle) {
      26:                     c[i].close = 1;
      27:                     c[i].read->handler(c[i].read);
      28:                 }
      29:             }
      30:  
      31:             if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
      32:             {
      33:                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
      34:                 ngx_worker_process_exit(cycle);
      35:             }
      36:         }
      37:  
      38:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
      39:  
      40:         ngx_process_events_and_timers(cycle);//处理事件的方法
      41:  
      42:         //强制结束进程
      43:         if (ngx_terminate) {
      44:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
      45:             ngx_worker_process_exit(cycle);
      46:         }
      47:  
      48:         //优雅地退出进程
      49:         if (ngx_quit) {
      50:             ngx_quit = 0;
      51:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
      52:                           "gracefully shutting down");
      53:             ngx_setproctitle("worker process is shutting down");
      54:  
      55:             if (!ngx_exiting) {
      56:                 ngx_close_listening_sockets(cycle);
      57:                 //设置ngx_exiting 标志位
      58:                 ngx_exiting = 1;
      59:             }
      60:         }
      61:  
      62:         //重新打开所有文件
      63:         if (ngx_reopen) {
      64:             ngx_reopen = 0;
      65:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
      66:             ngx_reopen_files(cycle, -1);
      67:         }
      68:     }
      69: }

     

    5.参考

    -

  • Echo Chen:Blog.csdn.net/chen19870707

    -

  • 菜鸟nginx源码剖析架构篇(二) nginx进程模型

    标签:des   style   blog   http   io   color   ar   os   sp   

    原文地址:http://blog.csdn.net/chen19870707/article/details/41245067

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!