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






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章