// -------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初始化大致流程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.