nginx 源代码分析 (三)
2021-06-19 本文已影响0人
RonZheng2010
1. ngx_event_core_module
nginx处理事件的接口是ngx_event_core_module模块。但不同系统上的系统接口不同,如epoll、select、kqueue等,每种接口都有自己的实现模块。ngx_event_core_module把事件处理委托给当前的实现。这里的实现模块使用ngx_epoll_module。
ngx_module_t ngx_event_core_module;
ngx_module_t ngx_epoll_module;
2. ngx_event_t
ngx_event_t用于保存处理事件的处理函数。
- 成员handler保存事件处理函数
- 成员data是与该事件关联的实例,如ngx_connection_t实例。
init_cycle.read_events[]和init_cycle.write_events[]是ngx_event_t数组,与
Init_cycle.connections[]大小相同,都是ngx_cycle_t.connection_n,并且元素一一对应。
3. ngx_event_module_init()
ngx_event_module_init()的主要工作是得到系统的资源限制值。
4. ngx_event_process_init()
ngx_event_module_init()的步骤如下。
- 调用ngx_queue_init(),初始化变量ngx_posted_events等,用于管理延迟事件。
- 调用ngx_event_timer_init(),初始化变量ngx_event_timer_rbtree,用于管理定时器事件。
- ngx_event_core_module将实际工作委托给真正的处理模块。它遍历所有NGX_EVENT_MODULE类型的模块,找到真正的处理模块,这里是ngx_epoll_module。
- ngx_event_core_module的配置数据ngx_core_conf_t.use保存了当前处理模块的索引,也就是ngx_module.ctx_index。
-
调用ngx_epoll_module::actions::init(),实际上是调用ngx_epoll_init()。
-
后面的步骤与init_cycle.connections[]和init_cycle.listening[]有关。主要是初始化它们,将服务器的监听连接加入epoll的监听列表。后面再详述。
4.1 ngx_epoll_init()
ngx_epoll_init()的步骤如下。
- 调用epoll_create()初始化epoll fd。
- 调用ngx_palloc()分配全局数组event_lists[],这是调用epoll_wait()时用来接收事件的数组。
struct epoll_event* event_list;
ngx_uint_t nevents;
- 将全局变量ngx_io指定为ngx_os_io。后面读写数据时,调用的函数就是在ngx_io中指定的。
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
ngx_readv_chain,
ngx_udp_unix_recv,
ngx_unix_send,
...
};
- 将全局变量ngx_event_actions指定为ngx_epoll_module.actions。后面在调用时就可以跳过ngx_event_core_module和ngx_epoll_module。这样可以省点事。
ngx_event_actions_t ngx_event_actions;
4.2 ngx_get_connection()
ngx_get_connection() 从init_cycle.free_connections[]数组中得到空闲连接。
5. ngx_add_event()
ngx_epoll_add_event() 开始按要求监听ngx_connection_t实例的事件。参数event是监听的事件类型,如可读、可写等。
ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
6. ngx_process_events()
ngx_epoll_process_events() 处理事件。
- 调用epoll_wait() 监听事件,触发的事件保存在全局数组event_list[]中。
- 遍历event_list[],对其中的epoll_event,进行处理。