// -------nginx.c-------
// 1. 入口函数主函数
int ngx_cdecl
main(int argc, char *const *argv)
{
//...
//...
/*获取配置信息*/
/*初始化相关信号量*/
/*初始化相当多的东西:包括初始化socket等等
参考:http://blog.csdn.net/chosen0ne/article/details/7754608
*/
cycle = ngx_init_cycle(&init_cycle); // 该函数还需作为一个单独单元解析----------------
//...
//...
if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle);
} else {
/*开始创建主进程*/
ngx_master_process_cycle(cycle);
}
return 0;
}
/*开始创建主进程,主进程循环处理*/
void
ngx_master_process_cycle(ngx_cycle_t *cycle)
{
//....
/*将相关信号添加进信号集中*/
//...
//...
/*开始创建子进程,start working*/
ngx_start_worker_processes(cycle, ccf->worker_processes,
NGX_PROCESS_RESPAWN);
ngx_start_cache_manager_processes(cycle, 0);
/*主进程也进入死循环中*/
for ( ;; ) {
//...
//...
if (delay){
/*定时器设置*/
}
//...
//...
/*是否有主进程终止信号*/
if (ngx_terminate) {
}
/*是否有子进程退出信号*/
if (ngx_quit) {
}
/*是否是重新加载配置信号*/
if (ngx_reconfigure) {
}
/*是否是重启信号*/
if (ngx_restart) {
}
}
}
/*开始创建子进程,start working*/
/*
参考:ngx_start_worker_processes子进程创建
http://blog.csdn.net/lengzijian/article/details/7589998
*/
static void
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
//...
//...
/*根据配置的子进程个数n,创建n个子进程*/
for (i = 0; i < n; i++) {
/*获取cpu个数*/
cpu_affinity = ngx_get_cpu_affinity(i);
/*产生一个处理子进程*/
ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
"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);
}
}
/*产生一个处理子进程*/
ngx_pid_t
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
char *name, ngx_int_t respawn)
{
//...
/*父子进程通信*/
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"socketpair() failed while spawning \"%s\"", name);
return NGX_INVALID_PID;
}
/*设置非阻塞*/
if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
//开启channel[0]的消息驱动IO
U_32 on = 1;
//FIOASYNC:设置/清楚信号驱动异步I/O标志
/*根据iocl 的第三个参数指向一个0 值或非0 值 ,分别清除或设置针对本套接口的信号驱动异步I/O 标志,
它决定是否收取针对本套接口的异步I/O 信号(SIGIO )。 本请求和O_ASYNC 文件状态标志等效,
而该标志可以通过fcntl 的F_SETFL 命令清除或设置。*/
if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"ioctl(FIOASYNC) failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//若进程执行了exec后,关闭socket
if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
// ...
/*创建子进程*/
pid = fork();
switch (pid) {
case -1:
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"fork() failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
case 0:
ngx_pid = ngx_getpid();
/*子进程执行函数*/
proc(cycle, data);
break;
default:
break;
}
//...
//...
return pid;
}
/*子进程执行函数*/
/*proc(cycle, data);proc函数就是执行ngx_worker_process_cycle 回调*/
/*具体解析:http://blog.csdn.net/xyyaiguozhe/article/details/11532415*/
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
// ...
/*子进程初始化*/
ngx_worker_process_init(cycle, 1);
/*死循环*/
for ( ;; ) {
// ...
/*子进程执行函数*/
ngx_process_events_and_timers(cycle);
}
}
/*子进程初始化函数*/
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
{
// ...
/*设置相关环境变量、组id等*/
/*各个模块的初始化函数*/
//如果是event module: ngx_event_process_init()被调用
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
//将其他进程的channel[1]关闭,自己的除外
//子进程继承了父进程的ngx_processes数组,但子进程只监听自己的channel[1]
//...
//将自己的channel[0]关闭
//因为自己的channel[0]是给其他子进程,用来发送消息的sendmsg
//...
//调用ngx_add_channel_event()函数,给ngx_channel注册一个读事件处理函数。
//在ngx_start_worker_processes()函数中,ngx_channel = ngx_processes[s].channel[1];
//ngx_channel就是进程自身的channel[1],用来读取的socket
//ngx_channel_handler处理从channel中收到的信号,当事件触发时,调用这个方法
if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler) == NGX_ERROR)
{
exit(2);
}
}
//如果是event module: ngx_event_process_init()被调用
/*事件模块的初始化*/
static ngx_int_t
ngx_event_process_init(ngx_cycle_t *cycle)
{
// ...
/*获取相关配置信息*/
// ...
/*获取模块上下文*/
module = ngx_modules[m]->ctx;
//初始化模块
/*ngx_epoll_module(类型ngx_module_t)是全局的结构变量,
在初始化的时候由ngx_epoll_module_ctx传入参数,而init函数也在这个时候确定 */
/*如epoll就是ngx_epoll_init,在ngx_epoll_init里面除了调用epoll_create外,最
重要的一步就是 ngx_event_actions = ngx_epoll_module_ctx.actions;钩子函数*/
if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
exit(2);
}
// ...
/*分配connection_n个空间给connections */
cycle->connections =
ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
//分配connection_n个空间给read_events和write_events,初始化这些read_events和write_events
cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
cycle->log);
cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
cycle->log);
/*将connections里面的读写事件一一关联起来并串成链表*/
i = cycle->connection_n;
next = NULL;
do {
i--;
c[i].data = next;
c[i].read = &cycle->read_events[i];
c[i].write = &cycle->write_events[i];
c[i].fd = (ngx_socket_t) -1;
next = &c[i];
} while (i);
/* for each listening socket */
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
// ...
/*主要将fd赋值给 c 里面的fd*/
c = ngx_get_connection(ls[i].fd, cycle->log);
}
// ...
/*设置c->read的handle为ngx_event_accept*/
rev->handler = ngx_event_accept;
// ...
return NGX_OK;
}
/*子进程执行函数*/
/*子进程处理事件函数*/
void
ngx_process_events_and_timers(ngx_cycle_t *cycle)
{
// ...
/*多进程加锁处理*/
if (ngx_use_accept_mutex) {
// ...
}
/*该宏定义为 #define ngx_process_events ngx_event_actions.process_events*/
/*即调用函数 ngx_epoll_process_events*/
(void) ngx_process_events(cycle, timer, flags);
}
/* accept 是在 ngx_epoll_process_events中的 rev->handler(rev);调用 */
/*
在 void ngx_event_accept(ngx_event_t *ev)函数的accept循环中,
靠后的位置有条调用语句 ls->handler(c);改钩子猜测应该
是调用void ngx_http_init_connection(ngx_connection_t *c)函数。
accetp后新建一个connect连接对象,下去再证实。
已证实 11/4
*/
Nginx初始化大致流程
最新推荐文章于 2022-11-16 17:44:44 发布