Nginx(七) 工作进程
一切从ngx_worker_process_init()函数开始:
1.先调用ngx_set_environment()函数为本进程设定环境变量,那些环境变量都是从cycle中继承过来的;
2. 有进程执行优先权,则调用setpriority(PRIO_PROCESS, 0, ccf->priority)函数设置优先权;
3. 设置进程可打开最大文件数(setrlimit(RLIMIT_NOFILE, &rlmt));
4. 设置内核转存文件最大长度(setrlimit(RLIMIT_CORE, &rlmt));
5. 支持RLIMIT_SIGPENDING的情况下,设置RLIMIT_SIGPENDING(setrlimit(RLIMIT_SIGPENDING, &rlmt));
6. 支持PR_SET_DUMPABLE时,设置PR_SET_DUMPABLE(prctl(PR_SET_DUMPABLE,1,0,0,0));
7. 换到当前工作的目录下;
8. 清空所有的信号;
9. 清掉监听socket上以前的事件;
10. 调用所的模块的init_process钩子函数;
11. 将其他进程的channel[1]关闭,自己的除外;
12. 将自己的channel[0]关闭;
13. 调用ngx_add_channel_event()函数,给ngx_channel(在ngx_start_worker_processes()函数中,ngx_channel = ngx_processes[s].channel[1];,所以ngx_channel就是进程自身的channel[1],用来读取的socket。)注册一个读事件处理函数;
注:其中重要变量ngx_process_slot的值是在ngx_spawn_process()函数中变动的。其他用到ngx_spawn_process变量,仅是读取其值。
ngx_add_channel_event()函数的主要工作:
1. 取得一个空闲的connection资源;
2. 创建了一个读事件和一个写事件对象,并设置了channel为1;
3. 检查注册的事件是读还是写,分别选用不同的事件对象,安装事件处理函数;
4. epoll事件模式并且ngx_event_actions.add_conn存在时,调用add_conn添加一个connection资源;否则用ngx_event_actions.add添加一个事件对象;
注:在linux环境下,epoll模式仅调用
ngx_channel_handler()函数,这个函数作为事件驱动:
1. 事件对象中的timedout清空;
2. 从事件对象中取得connection对象;
3. 进入循环,调用ngx_read_channel()函数,读取channel对象(还记得什么地方用ngx_write_channel()函数写向子进程写入一个channel对象吗?);
4. NGX_USE_EVENTPORT_EVENT事件标志时,添加读事件;
5. 接下来是检查取得的channel对象中的command,不同的命令不同的处理:
a) NGX_CMD_QUIT: ngx_quit = 1;
b) NGX_CMD_TERMINATE: ngx_terminate = 1;
c) NGX_CMD_REOPEN: ngx_reopen = 1;
d) NGX_CMD_OPEN_CHANNEL: 在ngx_processes[]表中指定项中设置pid和写文件描述符;
e) NGX_CMD_CLOSE_CHANNEL: 关闭ngx_processes[]表中指定表项中的写文件描述符。