现在的位置: 首页 > 综合 > 正文

January 7th Tuesday 2010

2013年08月28日 ⁄ 综合 ⁄ 共 2786字 ⁄ 字号 评论关闭

Nginx(六)

 

1. ngx_start_worker_processes()函数,这个函数按指定数目n,以ngx_worker_process_cycle()函数为参数调用ngx_spawn_process()创建work进程并初始化相关资源和属性;执行子进程的执行函数ngx_worker_process_cycle;向之前已经创建的所有worker广播当前创建的worker进程的信息;每个进程打开一个通道(ngx_pass_open_channel())

 

ngx_start_worker_processes()函数的主要逻辑如下:

a)  首先要说明的是参数respawn有两种含义:type 即创建新进程式的方式,如NGX_PROCESS_RESPAWN, NGX_PROCESS_JUST_RESPAWN…,是负值;另一种表示进程信息表的下标,此时是非负;

b)  查找ngx_processes[]进程信息表中一个空项;

c)  若不是分离的子进程(respawn != NGX_PROCESS_DETACHED)

i)    创建一对已经连接的无名socket

ii)  设置socket(channel[0]channel[1]))为非阻塞模式;

iii) 开启channel[0]的消息驱动IO

iv)  设置channel[0]的属主,控制channel[0]SIGIO信号只发给这个进程;

v)   设置channel[0]channel[1]FD_CLOEXEC属性(进程执行了exec后关闭socket)

vi)  取得用于监听可读事件的socket(ngx_channel = ngx_processes[s].channel[1];)

   

d)  分离的子进程时,ngx_processes[s].channel[0] = -1;
        ngx_processes[s].channel[1] = -1;

e)  设置当前子进程的进程表项索引;ngx_process_slot = s; 

f)  创建子进程;

g)  子进程式中,设置当前子进程的进程id,运行执行函数;

h)  respawn >= 0时,直接返回pid;

i)  设置其他的进程表项字段;

ngx_processes[s].proc = proc;
   ngx_processes[s].data = data;
   ngx_processes[s].name = name;
   ngx_processes[s].exiting = 0;

j)  根据respawn表示的类型,按不同方式设置表项。

 

创建socketpair用于进程间通信,master进程为每个worker创建一对socket master进程空间打开所有socketpairchannel[0]channel[1]两端句柄。 当创建一个worker的时候,这个worker会继承master当前已经创建并打开的所有socketpair,这个worker初始化的时候(调用ngx_worker_process_init)会关闭掉本进程对应socketpairchannel[0]和其他worker对应的channel[1],保持打开本进程对应socketpairchannel[1]和其他worker对应的channel[0],并监听本进程对应socketpairchannel[1]的可读事件。这样,每个worker就拥有了其他workerchannel[0],可以sendmsg(channel[0], ...)向其他worker发送消息。

 

先于当前worker创建的worker通过继承得到了其channel[0],但是之后创建的进程的channel[0]该如何获得呢,答案在上面(ngx_start_worker_processes) master在创建并启动完成一个worker之后,会调用ngx_pass_open_channel 把这个workerchannel[0]和进程id、在进程表中的偏移slot广播(ngx_write_channel())给所有其他已经创建的worker,这样,创建完所有进程之后,每个worker就获得了所有其他workerchannel[0]了。

 

ngx_worker_process_cycle()函数是每个进程的实际工作内容。这个函数中首先调用ngx_create_thread()初始化各线程。我们知道每个线程都有一个启动处理函数,nginx的线程处理函数为ngx_worker_thread_cycle(),内部过程中最重要的是对ngx_event_thread_process_posted()函数的调用,用于实际处理每一次请求。

 

初始化线程结束后,首先调用ngx_process_events_and_timers()函数,该函数继续调用ngx_process_events接口监听事件,一般情况下对应的函数是ngx_epoll_process_events(),如果使用的是其它种 类的IO模型,则应该实现相应的实际函数。这个接口负责把事件投递到ngx_posted_events事件队列里,并在 ngx_event_thread_process_posted()函数中进行处理。

2. ngx_start_cache_manager_processes()函数,这个函数在ngx_cycle全局对象的path数组中,检查是否有managerloader函数。有manage函数,创建缓冲管理进程,打开相应的通道,负责管理工作;有loader函数,创建缓冲管理进程,打开相应通道,负责载入工作。

3. ngx_pass_open_channel()函数,这个函数在全局的ngx_processes数组中所有pid不为-1channel[0]不为-1的进程打开通道。也就是为创建的每个work进程打开一个通道,发送消息(ngx_write_channel())给工作进程。

4. ngx_signal_worker_processes()函数,这个函数主要是向各个work进程发送一个信号。如果是ngx_signal_value(NGX_REOPEN_SIGNAL)信号,设ngx_processes中的标志exiting1

5. ngx_reap_children()函数,这个函数清理要退出的进程。ngx_processes数组中每个项保存对应一个进程的信号,有pidstatuschannel等。如果有子进程还没有退出exiting! detached,则live设为1

ngx_master_process_exit()函数,这个函数删除pid文件,接着调用模块中的exit_master钩子函数,销毁内存池。

抱歉!评论已关闭.