先看几个主要方法
-
ngx_add_channel_event 主要是把事件注册到事件池中,并且添加事件 handler,具体要结合后面的事件机制来展开。
-
ngx_write_channel 主要是将数据写入到 pipe 中:
n = sendmsg(s, &msg, 0);
Top of Form
Bottom of Form
-
ngx_read_channel 从 pipe 中读取数据:n = recvmsg(s, &msg, 0);
接下来分析事件模块工作流程
ngx_event模块结构
ngx_events_module 的数据结构如下:
ngx_module_t ngx_events_module = {
NGX_MODULE_V1,
&ngx_events_module_ctx, /* module context */
ngx_events_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
ngx_event 模块初始化
static ngx_command_t ngx_events_commands[] = {
{
ngx_string("events") ,
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS ,
ngx_events_block, 0, 0, NULL
},
ngx_null_command
};
通过 ngx_events_commands 数组可以知道,event 模块初始化函数为 ngx_events_block,该函数工作内容如下:
-
创建模块 context 结构
-
调用所有 NGX_EVENT_MODULE 模块的 create_conf
-
解析 event 配置
-
调用所有 NGX_EVENT_MODULE 模块的 init_conf
ngx_core_event模块初始化
ngx_core_event_module 是在 ngx_cycle_init 的时候初始化的:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_module) {
if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */
exit(1);
}
}
}
我们先来看下 ngx_core_event_module 的结构:
ngx_module_t ngx_event_core_module = {
NGX_MODULE_V1,
&ngx_event_core_module_ctx, /* module context */
ngx_event_core_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
ngx_event_module_init, /* init module */
ngx_event_process_init, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */ NGX_MODULE_V1_PADDING
};
ngx_event_module_init 实现了初始化过程,该过程分以下几个步骤:
-
连接数校验
-
初始化互斥锁
事件进程初始化
在工作线程初始化的时候,将会调用 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);
}
}
}
ngx_event_process_init 该过程分以下几步:
-
设置 ngx_accept_mutex_held
-
初始化定时器
-
初始化真正的事件引擎(linux 中为 epoll)
-
初始化连接池
-
添加 accept 事件
ngx_process_events_and_timers 事件处理开始工作
工作流程如下:
-
ngx_trylock_accept_mutex 当获取到标志位后才进行 accept 事件注册。
-
ngx_process_events 处理事件
-
释放 accept_mutex 锁
-
处理定时器事件
-
ngx_event_process_posted 处理 posted 队列的事件
ngx 定时器实现
ngx 的定时器利用了红黑树的实现
ngx 惊群处理
accept_mutex 解决了惊群问题,虽然linux的新内核已经解决了这个问题,但是ngx 是为了兼容。
整体原理图: