今回読むところ
- nginx-1.1.16
- core/nginx.c:200 mainから呼ばれるos/unix/ngx_process_cycle.c:295 ngx_single_process_cycleの中身。
その前に
GNU GLOBALを使おう。
$ brew install global
$ cd nginx-1.1.16
$ git init
$ gtags -v
$ cat .gitignore
GPATH
GRTAGS
GTAGS
Makefile
objs/
Emacsの例。
init-tags.el
(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
'(lambda ()
(local-set-key "\M-t" 'gtags-find-tag)
(local-set-key "\M-r" 'gtags-find-rtag)
(local-set-key "\M-s" 'gtags-find-symbol)
(local-set-key "\C-t" 'gtags-pop-stack)))
(add-hook 'c-mode-common-hook
'(lambda()
(gtags-mode 1)
(gtags-make-complete-list)))
void ngx_single_process_cycle(ngx_cycle_t *cycle)
cycleの定義
ngx_core.h
typedef struct ngx_cycle_s ngx_cycle_t;
ngx_core.h
struct ngx_cycle_s {
void ****conf_ctx;
ngx_pool_t *pool;
ngx_log_t *log;
ngx_log_t new_log;
ngx_connection_t **files;
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
ngx_queue_t reusable_connections_queue;
ngx_array_t listening;
ngx_array_t pathes;
ngx_list_t open_files;
ngx_list_t shared_memory;
ngx_uint_t connection_n;
ngx_uint_t files_n;
ngx_connection_t *connections;
ngx_event_t *read_events;
ngx_event_t *write_events;
ngx_cycle_t *old_cycle;
ngx_str_t conf_file;
ngx_str_t conf_param;
ngx_str_t conf_prefix;
ngx_str_t prefix;
ngx_str_t lock_file;
ngx_str_t hostname;
};
処理の流れ
- モジュール初期化
- メインループ突入
- イベント処理
- 終了条件チェック
- 再初期化チェック
- ログの再オープン
イベント処理
ngx_event.c
void ngx_process_events_and_timers(ngx_cycle_t *cycle)
- タイムアウト設定
- イベント監視
- イベント処理
ngx_event.c
(void) ngx_process_events(cycle, timer, flags);
ngx_process_eventsがなにやってるか。
ngx_event.h
#define ngx_process_events ngx_event_actions.process_events
// (snip)
typedef struct {
ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*add_conn)(ngx_connection_t *c);
ngx_int_t (*del_conn)(ngx_connection_t *c, ngx_uint_t flags);
ngx_int_t (*process_changes)(ngx_cycle_t *cycle, ngx_uint_t nowait);
ngx_int_t (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags);
ngx_int_t (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);
void (*done)(ngx_cycle_t *cycle);
} ngx_event_actions_t;
// (snip)
extern ngx_event_actions_t ngx_event_actions;
この関数ポインタがつまったstruct(クラスっぽい感じのやつ)ngx_event_actions
を、各event APIモジュールが実装している。
以下、select(2)の例。初期化時に、上記のメンバに実装を設定する:
ngx_select_module.c
ngx_event_actions = ngx_select_module_ctx.actions;
んでもって、process_eventsの実装はこんな感じ:
ngx_select_module.c
static ngx_int_t
ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
// (snip)
ngx_mutex_lock(ngx_posted_events_mutex);
nready = 0;
for (i = 0; i < nevents; i++) {
ev = event_index[i];
c = ev->data;
found = 0;
if (ev->write) {
if (FD_ISSET(c->fd, &work_write_fd_set)) {
found = 1;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select write %d", c->fd);
}
} else {
if (FD_ISSET(c->fd, &work_read_fd_set)) {
found = 1;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"select read %d", c->fd);
}
}
if (found) {
ev->ready = 1;
queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
&ngx_posted_events);
ngx_locked_post_event(ev, queue);
nready++;
}
}
ngx_mutex_unlock(ngx_posted_events_mutex);
// (snip)
以下略。