1 定义ngx_add_channel_event 函数 定义在 ./nginx-1.24.0/src/os/unix/ngx_channel.cngx_int_tngx_add_channel_event(ngx_cycle_t*cycle,ngx_fd_tfd,ngx_int_tevent,ngx_event_handler_pt handler){ngx_event_t*ev,*rev,*wev;ngx_connection_t*c;cngx_get_connection(fd,cycle-log);if(cNULL){returnNGX_ERROR;}c-poolcycle-pool;revc-read;wevc-write;rev-logcycle-log;wev-logcycle-log;rev-channel1;wev-channel1;ev(eventNGX_READ_EVENT)?rev:wev;ev-handlerhandler;if(ngx_add_conn(ngx_event_flagsNGX_USE_EPOLL_EVENT)0){if(ngx_add_conn(c)NGX_ERROR){ngx_free_connection(c);returnNGX_ERROR;}}else{if(ngx_add_event(ev,event,0)NGX_ERROR){ngx_free_connection(c);returnNGX_ERROR;}}returnNGX_OK;}ngx_add_channel_event 函数的主要作用是 将一个用于主从进程通信的管道/Socket 文件描述符fd注册到 Nginx 的事件循环中 并为其绑定读或写事件的回调处理函数。2 详解1 函数签名ngx_int_tngx_add_channel_event(ngx_cycle_t*cycle,ngx_fd_tfd,ngx_int_tevent,ngx_event_handler_pt handler)返回值 NGX_OK表示操作成功。 NGX_ERROR表示发生错误。参数1 ngx_cycle_t *cycle 指向当前运行周期上下文 参数2 ngx_fd_t fd 进程间通信的“通道”的文件描述符 参数3 ngx_int_t event 指定要监听的事件类型 NGX_READ_EVENT表示监听读事件。 NGX_WRITE_EVENT表示监听写事件。 参数4 ngx_event_handler_pt handler 函数指针指向当指定事件被触发时需要执行的回调函数 当事件循环如 epoll_wait返回该 fd 就绪时Nginx 事件分发器会执行 ev-handler(ev);2 逻辑流程1 局部变量 2 获取并初始化连接对象 3 事件监听 4 返回成功1 局部变量{ngx_event_t*ev,*rev,*wev;ngx_connection_t*c;c: 指向 ngx_connection_t 连接结构体的指针。 rev, wev: 分别指向该连接内嵌的读、写事件结构体的指针。 ev: 当前需注册的目标事件2 获取并初始化连接对象cngx_get_connection(fd,cycle-log);if(cNULL){returnNGX_ERROR;}获取连接对象c-poolcycle-pool;绑定内存池: 将连接对象 c 的内存池指针指向 cycle 的核心内存池3 事件监听3-1 事件设置revc-read;wevc-write;获取读写事件: 获取连接结构体内置的读事件 (c-read) 和写事件 (c-write) 的指针rev-logcycle-log;wev-logcycle-log;设置事件日志: 将读、写事件的日志对象都指向 cycle 的核心日志对象。 这样在这些事件的处理过程中产生的任何日志信息都会被统一记录便于调试和监控。rev-channel1;wev-channel1;标记为通道事件: 将读写事件的 channel 标志置为 1。 这个布尔标志用于标识该连接属于内部通信的“通道” 而非外部的客户端连接。ev(eventNGX_READ_EVENT)?rev:wev;确定目标事件: 根据传入的 event 参数将通用事件指针 ev 指向相应的读事件或写事件。 后续的事件添加操作将只针对这个具体的事件。ev-handlerhandler;设置回调函数: 将用户自定义的事件处理函数 handler 赋值给 ev-handler。 当文件描述符上发生所监听的事件时Nginx 的事件循环将调用此函数来处理。3-2 加入监听if(ngx_add_conn(ngx_event_flagsNGX_USE_EPOLL_EVENT)0){if(ngx_add_conn(c)NGX_ERROR){ngx_free_connection(c);returnNGX_ERROR;}}else{if(ngx_add_event(ev,event,0)NGX_ERROR){ngx_free_connection(c);returnNGX_ERROR;}}#1 它根据当前选定的事件模型来决定使用哪种接口来注册事件 ngx_event_flags: 这是一个全局的位掩码变量用于标识当前事件模型的各种特性 如是否支持边沿触发、是否为水平触发等。 NGX_USE_EPOLL_EVENT: 是该位掩码中的一个标志位当使用 epoll 模型时被设置。 ngx_add_conn: 是一个函数指针指向一次性添加整个连接的接口如 select/poll 等水平触发模型通常提供此接口。 整体含义: 如果当前事件模型提供了 ngx_add_conn 接口 并且 不是 epoll即其 NGX_USE_EPOLL_EVENT 标志未设置 则条件成立走下面的分支。 分支1 水平触发模型: 调用 ngx_add_conn(c)将整个连接对象同时包含读写事件一次性添加到事件监听中。 这适用于 select、poll 这类水平触发的模型。 如果添加失败调用 ngx_free_connection(c) 归还连接对象到连接池并返回 NGX_ERROR。#2 分支2边沿触发模型: 如果条件不成立例如使用了 epoll则走此分支。 epoll 模型通常不提供 ngx_add_conn 接口而是要求单独添加读或写事件。 因此调用 ngx_add_event(ev, event, 0)只将前面确定好的那个事件ev添加到监听中。 同样失败时需要释放连接并返回错误。4 返回成功returnNGX_OK;}