ngx_handle_read_event
1 定义ngx_handle_read_event 函数 定义在 ./nginx-1.24.0/src/event/ngx_event.cngx_int_tngx_handle_read_event(ngx_event_t*rev,ngx_uint_tflags){if(ngx_event_flagsNGX_USE_CLEAR_EVENT){/* kqueue, epoll */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,NGX_CLEAR_EVENT)NGX_ERROR){returnNGX_ERROR;}}returnNGX_OK;}elseif(ngx_event_flagsNGX_USE_LEVEL_EVENT){/* select, poll, /dev/poll */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,NGX_LEVEL_EVENT)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}if(rev-active(rev-ready||(flagsNGX_CLOSE_EVENT))){if(ngx_del_event(rev,NGX_READ_EVENT,NGX_LEVEL_EVENT|flags)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}}elseif(ngx_event_flagsNGX_USE_EVENTPORT_EVENT){/* event ports */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,0)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}if(rev-oneshotrev-ready){if(ngx_del_event(rev,NGX_READ_EVENT,0)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}}/* iocp */returnNGX_OK;}ngx_handle_read_event 函数 根据当前使用的事件驱动机制边沿触发、水平触发、事件端口、IOCP 统一管理读事件在内核监听中的添加与删除确保事件既不丢失也不反复通知同时避免忙轮询。2 详解1 函数签名ngx_int_tngx_handle_read_event(ngx_event_t*rev,ngx_uint_tflags)返回值 NGX_OK操作成功。 NGX_ERROR操作失败。参数 1 ngx_event_t *rev 指向要监听的事件 参数 2 ngx_uint_t flags 传递额外的控制标志影响函数对事件的处理策略2 逻辑流程1 边沿触发模式 2 水平触发模式 3 event ports 4 iocp{if(ngx_event_flagsNGX_USE_CLEAR_EVENT){/* kqueue, epoll */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,NGX_CLEAR_EVENT)NGX_ERROR){returnNGX_ERROR;}}returnNGX_OK;}elseif(ngx_event_flagsNGX_USE_LEVEL_EVENT){/* select, poll, /dev/poll */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,NGX_LEVEL_EVENT)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}if(rev-active(rev-ready||(flagsNGX_CLOSE_EVENT))){if(ngx_del_event(rev,NGX_READ_EVENT,NGX_LEVEL_EVENT|flags)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}}elseif(ngx_event_flagsNGX_USE_EVENTPORT_EVENT){/* event ports */if(!rev-active!rev-ready){if(ngx_add_event(rev,NGX_READ_EVENT,0)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}if(rev-oneshotrev-ready){if(ngx_del_event(rev,NGX_READ_EVENT,0)NGX_ERROR){returnNGX_ERROR;}returnNGX_OK;}}#1 判断是否为边沿触发模式 ngx_event_flags 是全局变量 记录了当前事件模块的特性位掩码。 NGX_USE_CLEAR_EVENT 置位表示使用 边沿触发机制。 该模式只通知一次事件就绪不会重复通知。注释提示该分支对应 FreeBSD 的 kqueue 和 Linux 的 epoll。条件判断 rev-active 表示该读事件是否已被加入内核事件监听集合 rev-ready 表示内核已将该事件标识为就绪 仅当事件既没有被监听也没有待处理的就绪状态时才需要重新添加事件监听。添加事件并检查结果 调用 ngx_add_event 将读事件加入内核监听 事件类型为 NGX_READ_EVENT 标志为 NGX_CLEAR_EVENT边沿触发。 若返回值等于 NGX_ERROR 表明添加失败 添加失败立即返回错误 由上层调用者处理边沿触发分支成功返回 事件要么已处于正确监听状态 要么刚被成功添加。#2 判断是否为水平触发模式 若 ngx_event_flags 中 NGX_USE_LEVEL_EVENT 置位 表示当前使用 水平触发机制。 该模式下只要有数据可读内核会一直通知。与边沿触发分支相同 当事件未被监听且未就绪时 才需要向内核注册监听。判断是否需要删除事件 在水平触发模式下 若事件仍在监听active 为真 且 已经就绪ready 为真 或 调用者要求关闭flags 包含 NGX_CLOSE_EVENT 则必须从内核监听集合中移除该事件。 就绪时不删除 内核会不断通知导致事件循环忙轮询busy loop。 关闭时不删除可能触发无效事件甚至访问已释放资源。删除读事件 调用 ngx_del_event 移除该读事件。 标志位通过 NGX_LEVEL_EVENT | flags 组合传入 以便底层如 poll可以根据 NGX_CLOSE_EVENT 跳过某些清理。#3 判断是否为 event ports 模式 Solaris 的 event ports 机制 行为类似边沿触发但支持一次性事件oneshot。 NGX_USE_EVENTPORT_EVENT 置位时使用该分支。4 iocp/* iocp */returnNGX_OK;}IOCP 下读写都由异步提交操作驱动 无需显式添加/删除监听事件。 所有未显式返回的路径统一至此返回成功。 这包括 IOCP 模式直接执行到此处。 水平触发模式下 active 为假或 active 为真但未就绪且无关闭标志。 event ports 模式下 oneshot 或 ready 为假。