在《關於nginx事件模組結構體的詳解》這篇文章中,我們講解nginx的事件模組的整體工作流程,並且著重講解了組織事件模組的各個方法的作用,本文則主要圍繞這整個流程,從原始碼的角度來講解nginx事件模組的實作細節。
1. ngx_events_block()
----events配置區塊解析
nginx在解析nginx.conf
設定檔時,如果目前解析的組態項目名稱為events
,且是一個設定區塊,則會呼叫ngx_events_block()
方法解析該配置區塊,如下是該方法的原始碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
|
ngx_events_block()
方法主要完成的工作有以下幾個:
● 呼叫ngx_count_modules()
方法對事件模組序號進行標記,需要注意的是,這裡的排序是針對當前模組在所有事件類型模組中的順序進行標記,並且將序號保存在各模組的ctx_index
屬性中,例如這裡的事件類型核心模組ngx_event_core_module
的ctx_index
就為0
;
● 為指標ctx
申請記憶體空間,並且申請一個數組,將其位址賦值給ctx指針,這裡的數組長度就為事件模組的數目。其實這裡的數組就是用來保存每個事件模組的配置物件的,當前事件模組在所有事件模組中的相對位置就對應於該數組中的相對位置,這裡的相對位置也即前一步中計算得到的ctx_index
;
● 呼叫各個事件模組的create_conf()
方法建立各自的配置結構體,並且將其保存在ctx
#指針指向的陣列中;
● 呼叫ngx_conf_parse()
方法對設定檔繼續解析,前面我們已經講到,ngx_events_block()
方法就是解析到events配置項的時候才呼叫的,因而這裡的ngx_conf_parse()
方法的呼叫就是繼續解析events配置塊的子配置項,而該方法調用完成則說明events
配置塊裡的配置項目都已經解析完成;
● 調用各個模組的init_conf()
方法對配置項進行初始化,簡單的說,就是,由於在nginx.conf
中只配置了部分配置項目的值,而剩餘的配置項就由init_conf()
方法來設定預設值;
2. ngx_event_init_conf( )
----檢查事件模組配置結構體是否正常建立
在nginx解析完nginx.conf設定檔的所有組態項目後(包括前一步講解的對events配置項的解析),就會呼叫所有核心模組的init_conf()方法對核心模組的配置項進行初始化。這裡的核心模組就包含ngx_events_module
,該模組的init_conf()
方法指向的就是這裡的ngx_event_init_conf()
方法,本質上並沒有做什麼工作,只是檢查了是否創建了儲存事件模組配置項的結構體數組。
如下是ngx_event_init_conf()
方法的原始碼:
1 2 3 4 5 6 7 8 |
|
上面兩個方法就是ngx_events_module
核心模組的兩個主要的設定方法,可以看到,這個核心模組的主要作用就是創建了一個數組,用於儲存各個事件模組的配置結構體的。下面我們來看看事件核心模組的主要方法。
3. ngx_event_core_create_conf()
----建立事件核心模組配置結構體
在第1點我們講到,解析events配置區塊的子配置項目之前,會呼叫各個事件模組的create_conf()
方法來建立其使用的儲存配置資料的結構體,而後呼叫ngx_conf_parse()
方法來解析子配置項,接著呼叫各個事件模組的init_conf()方法初始化各個模組配置資料的結構體。
這裡ngx_event_core_module_ctx
就是一個事件類型的模組,其create_conf屬性指向的就是ngx_event_core_create_conf()
方法,而init_conf
屬性屬性指向的就是ngx_event_core_init_conf()
方法。
這一節我們先講解ngx_event_core_create_conf()
方法的實作原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
可以看到,這裡的ngx_event_core_create_conf()
方法本質上就是建立了一個ngx_event_conf_t
結構體,並且將各個屬性都設為未設定狀態。
4. ngx_event_core_init_conf()
----初始化配置結構體
前面我們講到,在解析完各個子配置項目之後,nginx會呼叫各個事件模組的init_conf()
方法,這裡的核心事件模組就是這個ngx_event_core_init_conf()
方法,如下是該方法的原始碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
ngx_event_core_init_conf()方法的主要做了两件事:
● 选择当前所使用的模块,如果没指定,则默认使用第一个事件模块;
● 初始化事件核心模块的配置结构体的各个属性值为默认值。
5. ngx_event_module_init()
----核心模块的配置项初始化
对于ngx_event_core_module
模块而言,其还指定了两个方法,一个是用于初始化模块的ngx_event_module_init
()
方法,另一个是用于worker进程执行主循环逻辑之前进行调用的ngx_event_process_init()
方法。
ngx_event_module_init()
方法是在master进程中调用的,其会在解析完nginx.conf文件中的所有配置项之后调用,本质上,该方法的作用就是对当前配置的核心模块(事件模块)进行初始化。
如下是ngx_event_module_init()
方法的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
|
ngx_event_module_init()
方法主要完成的工作有如下几个:
● 获取配置的timer_resolution
属性值,并将其赋值给ngx_timer_resolution
属性,这个属性的作用主要是指定更新nginx缓存的时间的定时任务的执行时间间隔;
● 获取nginx配置的文件描述符和当前操作系统的文件描述符的配置,对比两个值,从而更新当前进程所能开启的文件描述符的个数;
● 声明一块共享内存,用于存储nginx进行统计用的各个属性的数据。
6. ngx_event_process_init()
----初始化worker进程
ngx_event_process_init()
方法主要是在worker进程执行主循环之前进行初始化调用的,如下是该方法的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
|
这里ngx_event_process_init()
方法主要完成了如下几个工作:
● 根据所使用的进程模式和worker进程数量,配置是否使用共享锁的字段ngx_use_accept_mutex
;
● 初始化用于处理事件的ngx_posted_accept_events
队列和ngx_posted_events
队列;
● 调用当前所使用的事件模型模块的init()方法,比如epoll模型在该init()方法中就会构建一个epoll句柄,以便后续往其中添加需要监听的事件;
● 判断是否配置了ngx_timer_resolution
属性,也即上一节中获取的更新nginx缓存时间的定时任务的执行频率字段,如果配置了,则创建一个定时任务以定时设置ngx_event_timer_alarm
属性值;
● 创建长度相同的connections
、read_events
和write_events
数组,并且将connections
数组中每个ngx_connection_t
结构体的read属性指向read_events
数组中对应位置的读事件结构体,将write属性指向write_events
数组中对应位置的写事件结构体,并且将所有的connections
组织成单链表存储到ngx_cycle_t
的free_connections
属性中;
● 为当前nginx监听的各个端口配置一个ngx_connection_t
结构体,并且为其添加对应的事件监听器,以等待客户端连接的到来。
6. 小结
本文主要讲解了nginx事件模块的初始化方式,以初始化过程中各个方法的调用顺序依次讲解了每个方法的实现原理,以及其在整个流程中所起到的作用。
推荐教程:Nginx教程
以上是講解nginx事件模組的實作細節的詳細內容。更多資訊請關注PHP中文網其他相關文章!