nginxをよむ
ソースコードリーディングが何ぼのもんじゃい
core/nginx.c if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); }
os/ngx_process_cycle.c ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); //後ろの方にはシグナルとかrestartの処理が書いてあった static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_spawn_process(cycle,ngx_worker_process_cycle,(void *) (intptr_t) i, "worker process", type); }
os/unix/ngx_process.c ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn){ //省略 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; } //省略 }
procが関数として呼び出されている
procの型はngx_spawn_proc_pt(なんだこりゃ
os/unix/ngx_process.h typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data);
ngx_spawn_proc_ptは上記二つの引数をとる関数の型
呼び出し元を見るとos/unix/ngx_process_cycle.cのngx_worker_process_cycle
os/unix/ngx_process_cycle.c static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) { //~ ngx_process_events_and_timers(cycle); //~ }
./event/ngx_event.c:194 void ngx_process_events_and_timers(ngx_cycle_t *cycle){ //~ (void) ngx_process_events(cycle, timer, flags); //~ }
./event/ngx_event.h:408 #define ngx_process_events ngx_event_actions.process_events
わった
検索結果
[root@hote src]# grep -rne ngx_event_actions ./ ./event/modules/ngx_win32_select_module.c:106: ngx_event_actions = ngx_select_module_ctx.actions; ./event/modules/ngx_devpoll_module.c:186: ngx_event_actions = ngx_devpoll_module_ctx.actions; ./event/modules/ngx_epoll_module.c:368: ngx_event_actions = ngx_epoll_module_ctx.actions; ./event/modules/ngx_eventport_module.c:279: ngx_event_actions = ngx_eventport_module_ctx.actions; ./event/modules/ngx_kqueue_module.c:224: ngx_event_actions = ngx_kqueue_module_ctx.actions; ./event/modules/ngx_poll_module.c:96: ngx_event_actions = ngx_poll_module_ctx.actions; ./event/modules/ngx_select_module.c:105: ngx_event_actions = ngx_select_module_ctx.actions; ./event/ngx_event.c:44:ngx_event_actions_t ngx_event_actions;
環境と方式によって違うメソッドを実行している
/event/modules/ngx_eventport_module.c:279
static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer) { //~ ngx_event_actions = ngx_epoll_module_ctx.actions; //~ }
/event/ngx_event.c
static char * ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_event_conf_t *ecf = conf; #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL) int fd; #endif ngx_int_t i; ngx_module_t *module; ngx_event_module_t *event_module; module = NULL; #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL) fd = epoll_create(100); if (fd != -1) { (void) close(fd); module = &ngx_epoll_module; } else if (ngx_errno != NGX_ENOSYS) { module = &ngx_epoll_module; } } |||< 切り替えをしているのはこの部分 (パラメータで切り替えるのになぜマクロ?) (気力が失せた) module_epoll >|| ngx_event_module_t ngx_epoll_module_ctx = { &epoll_name, ngx_epoll_create_conf, /* create configuration */ ngx_epoll_init_conf, /* init configuration */ { ngx_epoll_add_event, /* add an event */ ngx_epoll_del_event, /* delete an event */ ngx_epoll_add_event, /* enable an event */ ngx_epoll_del_event, /* disable an event */ ngx_epoll_add_connection, /* add an connection */ ngx_epoll_del_connection, /* delete an connection */ #if (NGX_HAVE_EVENTFD) ngx_epoll_notify, /* trigger a notify */ #else NULL, /* trigger a notify */ #endif ngx_epoll_process_events, /* process the events */ ngx_epoll_init, /* init the events */ ngx_epoll_done, /* done the events */ } };
このうちのactionsに対応する部分を実行している
events.h
typedef struct { ngx_str_t *name; void *(*create_conf)(ngx_cycle_t *cycle); char *(*init_conf)(ngx_cycle_t *cycle, void *conf); ngx_event_actions_t actions; } ngx_event_module_t;
actionsに相当するのは関数のリストであるぞ
このリストの中でメインループなのはprocess_events
なかでepoll掘って完了したイベントごとに何かしている感じ