January 11th Monday 2010

来源:互联网 发布:泰安知金教育的校长 编辑:程序博客网 时间:2024/06/06 08:57

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. 创建了一个读事件和一个写事件对象,并设置了channel1

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[]表中指定表项中的写文件描述符。