Nginx初始化大致流程

// -------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
*/






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值