微信公眾號:鄭爾多斯
關注可瞭解更多的Nginx知識。任何問題或建議,請公眾號留言;
關注公眾號,有趣有內涵的文章第一時間送達!
事件機制
下面是我們對nginx事件相關的配置,如下:
1events {
2 worker_connections 1024;
3 use epoll;
4}
複製程式碼
我們明確的使用了epoll機制,在nginx中,和事件相關的模組一共有三個,分別為ngx_events_module
,ngx_event_core_module
,ngx_epoll_module
。
本篇文章介紹ngx_events_module
模組。
ngx_events_module
該模組是nginx中引入事件機制的模組,我們可以從ngx_events.c
檔案中找到與ngx_events_module
相關的配置,如下:
1static ngx_command_t ngx_events_commands[] = {
2
3 { ngx_string("events"),
4 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
5 ngx_events_block,
6 0,
7 0,
8 NULL },
9
10 ngx_null_command
11};
12
13
14static ngx_core_module_t ngx_events_module_ctx = {
15 ngx_string("events"),
16 NULL,
17 ngx_event_init_conf
18};
19
20
21ngx_module_t ngx_events_module = {
22 NGX_MODULE_V1,
23 &ngx_events_module_ctx, /* module context */
24 ngx_events_commands, /* module directives */
25 NGX_CORE_MODULE, /* module type */
26 NULL, /* init master */
27 NULL, /* init module */
28 NULL, /* init process */
29 NULL, /* init thread */
30 NULL, /* exit thread */
31 NULL, /* exit process */
32 NULL, /* exit master */
33 NGX_MODULE_V1_PADDING
34};
35
36typedef struct {
37 ngx_str_t name;
38 void *(*create_conf)(ngx_cycle_t *cycle);
39 char *(*init_conf)(ngx_cycle_t *cycle, void *conf);
40} ngx_core_module_t;
複製程式碼
從上面的配置中我們可以得到如下資訊:
ngx_events_module
是一個核心模組 (NGX_CORE_MODULE
型別)ngx_events_module
只解析一個命令,即events
這個NGX_BLOCK
命令,並且不帶引數ngx_events_module
的create_conf()
函式為空,它只有init_conf()
函式- 當遇到
events
指令的時候,呼叫ngx_event_block()
函式進行解析處理
解析events指令
我們在前面的文章中介紹過,配置檔案的解析是在ngx_init_cycle()
函式中完成的。我們再次把這部分程式碼摘出來,如下:
1cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
2 if (cycle->conf_ctx == NULL) {
3 ngx_destroy_pool(pool);
4 return NULL;
5 }
複製程式碼
這裡分配conf_ctx
的記憶體空間,然後執行如下的程式碼:
1for (i = 0; cycle->modules[i]; i++) {
2 if (cycle->modules[i]->type != NGX_CORE_MODULE) {
3 continue;
4 }
5
6 module = cycle->modules[i]->ctx;
7
8 if (module->create_conf) {
9 rv = module->create_conf(cycle);
10 if (rv == NULL) {
11 ngx_destroy_pool(pool);
12 return NULL;
13 }
14 cycle->conf_ctx[cycle->modules[i]->index] = rv;
15 }
16 }
複製程式碼
遍歷所有的NGX_CORE_MODULE
型別的模組,呼叫他們的create_conf()
方法,並且賦值給cycle->conf_ctx
,上面分析過,ngx_event_module
並沒有create_conf()
方法,所以這部分程式碼對ngx_event_module
沒有影響。
ngx_events_block
下面我麼分析一下ngx_events_block()
函式,這個函式的作用就是解析events
指令,程式碼如下:
1static char *
2ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3{
4 char *rv;
5 void ***ctx;
6 ngx_uint_t i;
7 ngx_conf_t pcf;
8 ngx_event_module_t *m;
9
10 if (*(void **) conf) {
11 return "is duplicate";
12 }
13
14 /* count the number of the event modules and set up their indices */
15
16 ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE);
17
18 ctx = ngx_pcalloc(cf->pool, sizeof(void *));
19 if (ctx == NULL) {
20 return NGX_CONF_ERROR;
21 }
22
23 *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
24 if (*ctx == NULL) {
25 return NGX_CONF_ERROR;
26 }
27
28 *(void **) conf = ctx;
29
30 for (i = 0; cf->cycle->modules[i]; i++) {
31 if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
32 continue;
33 }
34
35 m = cf->cycle->modules[i]->ctx;
36
37 if (m->create_conf) {
38 (*ctx)[cf->cycle->modules[i]->ctx_index] =
39 m->create_conf(cf->cycle);
40 if ((*ctx)[cf->cycle->modules[i]->ctx_index] == NULL) {
41 return NGX_CONF_ERROR;
42 }
43 }
44 }
45
46 pcf = *cf;
47 cf->ctx = ctx;
48 cf->module_type = NGX_EVENT_MODULE;
49 cf->cmd_type = NGX_EVENT_CONF;
50
51 rv = ngx_conf_parse(cf, NULL);
52
53 *cf = pcf;
54
55 if (rv != NGX_CONF_OK) {
56 return rv;
57 }
58
59 for (i = 0; cf->cycle->modules[i]; i++) {
60 if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
61 continue;
62 }
63
64 m = cf->cycle->modules[i]->ctx;
65
66 if (m->init_conf) {
67 rv = m->init_conf(cf->cycle,
68 (*ctx)[cf->cycle->modules[i]->ctx_index]);
69 if (rv != NGX_CONF_OK) {
70 return rv;
71 }
72 }
73 }
74
75 return NGX_CONF_OK;
76}
複製程式碼
該函式的執行流程如下:
- 計算當前有多少個
NGX_EVENT_MODULE
型別的模組,我們這裡的例子中有兩個該型別的模組- 分配記憶體空間
- 呼叫所有
NGX_EVENT_MODULE
型別模組的create_conf()
方法- 遞迴解析
events
塊指令的內部指令,比如use
,worker_connections
等指令- 呼叫所有
NGX_EVENT_MODULE
型別模組的init_conf()
方法
上面就是ngx_events_block()
方法的執行流程。這個方法很簡單,因為牽涉到ngx_event_core_module
和 ngx_epoll_module
,所以下一節我們詳細介紹一下這兩個事件模組。
喜歡本文的朋友們,歡迎長按下圖關注訂閱號鄭爾多斯,更多精彩內容第一時間送達