值得参考的链接:https://tengine.taobao.org/book/module_development.html
多进程模式:
ngx_master_process_cycle(cycle);
(1)设置进程标题
(2)开启工作进程,ngx_start_worker_processes(conf_ctx, core_module);
(3)开启缓存管理进程, ngx_start_cache_manager_processes(cycle, 0);
(4)进入循环,捕捉进程中发生的信号,针对信号做不同的处理
4.1: 热更新配置的处理流程:
if (ngx_new_binary) { <----nginx二进制文件更新
ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN);
ngx_start_cache_manager_processes(cycle, 0);
// 设置某些标识
continue;
}
// 更新cycle,重启工作进程和缓存管理线程
cycle = ngx_init_cycle(cycle);
ngx_cycle = cycle;
ccf = ngx_get_conf(cycle->conf_ctx, ngx_core_module);
ngx_start_worker_processes();
ngx_start_cache_manager_processes();
// 暂停100秒,等待新进程开启
ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
ngx_start_worker_processes(cycle, proc_num, type)的流程:
channel_t ch;
ch.command = NGX_CMD_OPEN_CHANNEL;
for(int i=0; i<proc_num; i++) {
/* 衍生一个新进程,新进程执行ngx_worker_process_cycle函数 */
ngx_spawn_process(cycle, ngx_worker_process_cycle,
(void *)(intptr_t)i, "worker process", type);
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
/*
ngx_pass_open_channel(cycle, &ch);
}
nginx中fork进程的代码:
pid = fork();
switch(pid) {
case -1:
// 错误处理,
case 0:
proc(cycle, data); // 执行ngx_worker_process_cycle函数,参数为cycle和data
break;
default:
break;
}
ngx_worker_process_cycle函数处理流程:
worker = (intptr_t) data; /* 作用是什么? */
ngx_worker_process_init(cycle, worker);
// 设置进程标题
// 进入for循环
(1)判断进程中ngx_exiting全局标识是否为true, 是则进程终止
(2)ngx_process_events_and_timer(cycle); // 处理cycle中发生的事件,关键函数;
(3)判断其他全局状态变量,调用相应的处理函数
ngx_process_events_and_timers(cycle)的处理流程:
if (ngx_use_accept_mutex) {
if (ngx_accept_disabled > 0) //
ngx_accept_disabled--;
else {
if (ngx_trylock_accept_mutex(cycle) == ERROR) // 获取互斥锁失败返回
return;
}
}
delta = ngx_current_msec; //事件处理的开始事件
ngx_process_events(cycle, timer, flags); <--- 事件处理的主要函数,
选择的I/O模型不同,ngx_process_events函数也不
一样;分析epoll I/O模型的事件处理过程;
对应epoll模块中ngx_epoll_process_events函数
delta = ngx_current_msec - delta;
ngx_event_process_posted(cycle, &ngx_posted_accept_events); <--- 事件后处理函数
epoll I/O模型事件处理code在event/module/ngx_epoll_module.c文件中定义;
自定义的epoll_event数据结构
typedef union epoll_data { <---一个联合体数据类型
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; <---事件个数
epoll_data_t data; <---具体的事件数据
};
epoll I/O模型处理事件的具体代码流程:
events = epoll_wait(ep, event_list, (int)nevent, timer); <--等待发生在ep上的事件,
nevnets限制最大的事件数
err = (events == -1) ? ERROR : 0;
// 循环处理事件列表
for (i=0; i<events; i++) {
c = event_lists[i].data.ptr;
instance = (uintptr_t) c & 1; // 判断c最后一位是否是0?
c = (ngx_connection *)((uintptr_t)c & (uintptr_t) ~1); /*将c转为指向ngx_connection_t类型指针;*/
// 针对ngx_connection_t类型数据进行操作;
rev = c->read; <--- ngx_event_t类型的读事件
//
}