本文共 6934 字,大约阅读时间需要 23 分钟。
typedef struct { ngx_str_t *name; // 事件模块名称 /* 创建存储events{}中配置项的结构体 */ void *(*create_conf)(ngx_cycle_t *cycle); /* 初始化操作,用以处理事件模块感兴趣的配置项 */ char *(*init_conf)(ngx_cycle_t *cycle, void *conf); /* 重要!每个事件模块需要实现10种抽象方法 */ ngx_event_actions_t actions;} ngx_event_module_t;
typedef struct { /* 添加/删除事件,负责在事件驱动机制里(如epoll中)添加/删除 感兴趣的事件 */ ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); /* 启动/禁用事件,目前不会调用此2种方法,代码中实现方式跟添加/删除一致 */ ngx_int_t (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); ngx_int_t (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); /* 添加/删除新的连接,复杂在事件驱动机制里(如epoll)添加/删除新的连接, * 这意味着新连接上的读写事件都将被事件驱动关注 */ ngx_int_t (*add_conn)(ngx_connection_t *c); ngx_int_t (*del_conn)(ngx_connection_t *c, ngx_uint_t flags); /* 具体的事件处理方法 */ ngx_int_t (*process_changes)(ngx_cycle_t *cycle, ngx_uint_t nowait); ngx_int_t (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags); /* 事件驱动模块的初始化及结束方法 */ ngx_int_t (*init)(ngx_cycle_t *cycle, ngx_msec_t timer); void (*done)(ngx_cycle_t *cycle);} ngx_event_actions_t;
struct ngx_event_s { /* 事件相关的对象,通常指向ngx_connection_t连接对象 */ void *data; /* 标志位,标识事件可写,意味着对应的TCP连接可写,也即连接处于发送网络包状态 */ unsigned write:1; /* 标志位,标识可建立新的连接,一般是在ngx_listening_t对应的读事件中标记 */ unsigned accept:1; /* used to detect the stale events in kqueue, rtsig, and epoll */ /* 用于区分当前事件是否过期,这涉及到一个很好的小技巧,后续会专门介绍 */ unsigned instance:1; /* * the event was passed or would be passed to a kernel; * in aio mode - operation was posted. */ /* 标志位,标识当前事件是否活跃 */ unsigned active:1; /* 标志位,标识当前事件是否禁用 */ unsigned disabled:1; /* the ready event; in aio mode 0 means that no operation can be posted */ /* 标志位,标识当前事件是否准备好,为1时表示可以被相应消费模块进行处理 */ unsigned ready:1; /* 对epoll来说无意义,不笔记,我也不懂... */ unsigned oneshot:1; /* aio operation is complete */ /* 标志位,用于AIO异步事件的处理 */ unsigned complete:1; unsigned eof:1; // 当前处理的字符流结束符 unsigned error:1; // 事件处理错误 unsigned timedout:1; // 超时标识 unsigned timer_set:1; // 标志该事件处于定时器中 unsigned delayed:1; // 需要延迟处理事件 unsigned deferred_accept:1; // 未使用 /* the pending eof reported by kqueue, epoll or in aio chain operation */ unsigned pending_eof:1; #if !(NGX_THREADS) unsigned posted_ready:1; // 表示处理post事件时,当前事件准备就绪#endif#if (NGX_WIN32) /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */ unsigned accept_context_updated:1;#endif#if (NGX_HAVE_KQUEUE) unsigned kq_vnode:1; /* the pending errno reported by kqueue */ int kq_errno;#endif /* * kqueue only: * accept: number of sockets that wait to be accepted * read: bytes to read when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * write: available space in buffer when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * * iocp: TODO * * otherwise: * accept: 1 if accept many, 0 otherwise */#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP) int available;#else unsigned available:1; // 在epoll机制下,标识一次尽可能多的建立TCP连接#endif /* 事件发生时的处理函数,每个事件消费模块都会重新实现它 */ ngx_event_handler_pt handler;#if (NGX_HAVE_AIO)#if (NGX_HAVE_IOCP) ngx_event_ovlp_t ovlp;#else struct aiocb aiocb;#endif#endif ngx_uint_t index; ngx_log_t *log; ngx_rbtree_node_t timer; // 定时器节点,用于定时器红黑树中 unsigned closed:1; /* to test on worker exit */ unsigned channel:1; unsigned resolver:1;#if (NGX_THREADS) unsigned locked:1; unsigned posted_ready:1; unsigned posted_timedout:1; unsigned posted_eof:1;#if (NGX_HAVE_KQUEUE) /* the pending errno reported by kqueue */ int posted_errno;#endif#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP) int posted_available;#else unsigned posted_available:1;#endif ngx_atomic_t *lock; ngx_atomic_t *own_lock;#endif /* the links of the posted queue */ /* post事件双向链表 */ ngx_event_t *next; ngx_event_t **prev;#if 0 /* the threads support */ /* * the event thread context, we store it here * if $(CC) does not understand __thread declaration * and pthread_getspecific() is too costly */ void *thr_ctx;#if (NGX_EVENT_T_PADDING) /* event should not cross cache line in SMP */ uint32_t padding[NGX_EVENT_T_PADDING];#endif#endif}每一个事件最核心的部分就是handler回调方法,它将由每一个事件消费模块实现,以此决定这个事件究竟如何“消费”。原型如下:
typedef void (*ngx_event_handler_pt)(ngx_event_t *ev);所有Nginx模块只要进行事件处理就必然要设置handler回调方法。
#define ngx_add_event ngx_event_actions.add#define ngx_del_event ngx_event_actions.del#define ngx_add_conn ngx_event_actions.add_conn#define ngx_del_conn ngx_event_actions.del_conn
转载地址:http://frpad.baihongyu.com/