nginx中的事件模块是一个很重要的模块,但这里作为初读,我们只简单看一下ngx_event的数据结构,至于模块和机制,留作之后再分析。

下面是结构体ngx_event_t的代码:

typedef struct ngx_event_s    ngx_event_t;
struct ngx_event_s {void            *data;/* 事件上下文数据,通常data都是指向ngx_connection_t连接对象。* 开启文件异步I/O时,它可能会指向ngx_event_aio_t结构体。* ... ngx_int_t ngx_handle_write_event(ngx_event_t *wev, size_t lowat) {ngx_connection_t  *c;if (lowat) {c = wev->data;       // 在这里event的data就指向了connection_t,直接用指针获取if (ngx_send_lowat(c, lowat) == NGX_ERROR) {return NGX_ERROR;}}...} ...unsigned         write:1; /* 标志位,为1时表示事件是可写的。通常它表示对应的TCP连接可写,也就是连接处于可以发送网络包的状态。*/unsigned         accept:1; /* 标志位,为1时表示为此事件可以建立新的连接。通常在ngx_cycle_t中的listening动态数组中,每一个监听对象ngx_listening_t,对应的读事件中的accept标志位才会是1。*/unsigned         instance:1;/* used to detect the stale events in kqueue, rtsig, and epoll* 这个标志位用于区分当前事件是否过期,它仅仅是给事件驱动模块使用的,而事件消费模块可不用关心。* 为什么需要这个标志位呢?当开始处理一批事件时,处理前面的事件可能会关闭一些连接,而这些连接有可能影响这批事件中还未处理到的后面的事件,这时可通过instance来避免处理后面的过期事件。*/unsigned         active:1;/* the event was passed or would be passed to a kernel;* in aio mode - operation was posted.* 标志位,为1表示当前事件是活跃的,为0表示事件是不活跃的。* 这个状态对应着事件驱动模块处理方式的不同。例如,在添加事件,删除事件和处理事件时,active标志位的不同都会对应着不同的处理方式。在使用事件时,一般不会直接改变active标志位。* ... if (!rev->delayed) {if (rev->active && !rev->ready) {ngx_add_timer(rev, p->read_timeout);} else if (rev->timer_set) {ngx_del_timer(rev);}    } ...*/unsigned         disabled:1;/* 标志位,为1表示禁用事件,仅在kqueue或者rtsig事件驱动模块中有效,对于epoll事件驱动模块则没有意义。* ... if (c->read->active || c->read->disabled) {   ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);} ...   // 位于close_connection函数中*//unsigned         ready:1;/* the ready event; in aio mode 0 means that no operation can be posted * 标志位,为1表示当前事件准备就绪,也就是说,允许这个事件的handler处理这个事件。* 在HTTP框架中,经常会检查事件的ready标志位,以确定是否可以接收请求或者发送相应。* ... if (rev->ready) {if (ngx_use_accept_mutex) {ngx_post_event(rev, &ngx_posted_events);return;}rev->handler(rev);return;} ...*/     unsigned         oneshot:1;/* 该标志位仅对kqueue,eventport等模块有意义,而对于linux上的epoll事件驱动模块则是无意义的。*/unsigned         complete:1;/* aio operation is complete* 用于异步aio事件的处理 */unsigned         eof:1;unsigned         error:1;/* 标志位,eof表示当前处理的字符流已经结束,error表示事件处理过程出错了。 * ... flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0; ...*/unsigned         timedout:1;/* 标志位,为1表示这个事件超时,用以提示handler做超时处理,它与timer_set都用了定时器 * ... if (wev->timedout) {wev->timedout = 0;ngx_http_perl_handle_request(r);return;} ...*/unsigned         timer_set:1;/* 标志位,为1表示这个事件存在于定时器中* ... if (!ngx_cleaner_event.timer_set) {ngx_add_timer(&ngx_cleaner_event, 30000);ngx_cleaner_event.timer_set = 1;} ...*/      unsigned         delayed:1;/* 标志位,delayed为1表示需要延迟处理这个事件,它仅用于限速功能 */unsigned         deferred_accept:1;/* 标志位,为1表示延迟建立TCP连接,也就是TCP三次握手后并不建立连接,而是等到真正收到数据包后才建连接 */unsigned         pending_eof:1;/* the pending eof reported by kqueue, epoll or in aio chain operation * 标志位,为1表示等待字符流结束,它只与kqueue和aio事件驱动机制有关 */unsigned         posted:1;#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;
#elseunsigned         available:1;
#endifngx_event_handler_pt  handler;/* 这个事件发生时的处理方法,每个事件处理模块都会重新实现它 */#if (NGX_HAVE_AIO)// win下的一种事件驱动模型
#if (NGX_HAVE_IOCP)    ngx_event_ovlp_t ovlp;
#else      // 在linux中定义的aio结构体            struct aiocb     aiocb;
#endif#endifngx_uint_t       index;/* epoll 事件驱动方式不使用index */ngx_log_t       *log;/* 记录当前event的log对象 */ngx_rbtree_node_t   timer; /* 定时器节点,用于定时器红黑树中 *//* the posted queue */ngx_queue_t      queue;unsigned         closed:1;/* to test on worker exit */unsigned         channel:1;unsigned         resolver:1;unsigned         cancelable:1;#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
};                                                        

我们再看一下event.h里一个数据结构:

typedef struct {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);/* 添加/移出事件方法,负责把事件添加/移出到操作系统提供的事件驱动机制(如epoll,kqueue等)中,这样在事件发生之后,将可以/无法调用下面的process_envets时获取这个事件。*/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);/* 启用/禁用一个事件,目前事件框架不会调用,大部分事件驱动模块对该方法的实现都与add/del完全一致 */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_events)(ngx_cycle_t *cycle, ngx_msec_t timer,ngx_uint_t flags);/* 在正常的工作循环中,将通过调用process_events方法来处理事件。* 这个方法仅在ngx_process_events_and_timers方法中调用,它是处理分发事件的核心。*/ngx_int_t  (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);void       (*done)(ngx_cycle_t *cycle);/* 初始化和退出事件驱动模块的方法 */
} ngx_event_actions_t;extern ngx_event_actions_t   ngx_event_actions;

作为nginx中比较重要的一个驱动,event当然是很复杂的,第一遍看反正怎么也不容易懂,后续刨析了nginx的各种机制和流程应该就很容易懂了,先放过它,继续往下看。

贴个链接:https://segmentfault.com/a/1190000002715203

--------------------- 本文来自 醇雾 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/wuchunlai_2012/article/details/50731037?utm_source=copy

nginx源码初读(8)--让烦恼从数据结构开始(ngx_event)相关推荐

  1. nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)

    抛去所有的模块和各种定义的数据结构,对于一个没看过这么大工程的小白来说,太乱!乱的不要不要,光是各种数据结构的含义,就让我要抓狂了.好吧,我并不是说它结构不好,相反我感觉代码写的太棒了..就是一时间. ...

  2. 16w行的nginx源码,如何才能读懂呢?全面分析nginx的机制

    16w行的nginx源码,如何才能读懂呢?全面分析nginx的机制 1. nginx的轮子组成 2. nginx的epoll实现机制 3. nginx的内存机制 视频讲解如下,点击观看: 16w行的n ...

  3. 设计模式在C语言中的应用--读nginx源码

    市面上的"设计模式"书籍文章,皆针对Java/C++/C#等面向对象语言,似乎离开了面向对象的种种特性,设计模式就无法实现,没有用武之地了. 是这样吗?设计模式的概念是从建筑领域引 ...

  4. Nginx源码分析--数据对齐posix_memalign和memalign函数

    posix_memalign函数() /*  * 背景:  *      1)POSIX 1003.1d  *      2)POSIX 标明了通过malloc( ), calloc( ), 和 re ...

  5. Nginx源码分析:epoll事件处理模块概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...

  6. Nginx源码分析:惊群处理与负载均衡

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> Nginx的惊群处理与负载均衡概述 当Nginx工作在master/worker模式下时,就 ...

  7. Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...

  8. Nginx源码分析:启动流程

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> nginx简介 Nginx的作为服务端软件,表现的主要特点是更快.高扩展.高可靠性.低内存消 ...

  9. nginx模块_使用gdb调试nginx源码

    工欲善其事必先利其器,如何使用调试工具gdb一步步调试nginx是了解nginx的重要手段. ps:本文的目标人群是像我这样初接触Unix编程的同学,如果有什么地方错误请指正. 熟悉gdb的使用 这里 ...

最新文章

  1. 10.4 再探迭代器-插入/IO/反向
  2. Python字符串讲解举例—工资字符串
  3. 110. Balanced Binary Tree
  4. 字符串得结果!Java数组模拟栈以实现中缀表达式综合计算器,字符串表达式计算器
  5. python提示对话框自动关闭_Python实现定时自动关闭的tkinter窗口方法
  6. 本周四直播预告(内含福利)丨 Oracle RAC集群安装部署
  7. linux自动重启电脑脚本,linux下通过脚本实现自动重启程序的方法
  8. iOS最为简单时间轴(GZTimeLine)
  9. ARM指令集与Thumb指令集--区别关联--汇编指令 BX LR ; 跳转回LR地址处,既可以是ARM模式也可以是Thumb模式
  10. ARP过程——删除地址映射
  11. Yum介绍与常见用法
  12. python基础之练习题(二)
  13. Nokia手机S40平台手机开发环境的搭建的过程
  14. 国密标准Ukey在Web登录认证流程
  15. 1024程序员节CSDN活动征文:数据结构之顺序表
  16. jlink怎么调试linux程序_Ubuntu12.10 使用JLink连接开发板用arm-gdb调试ARM程序
  17. m3u8 格式影片加載
  18. TypeError: classification_report() takes 2 positional arguments but 3 were given的解决方案
  19. 瑞克斯平台国际时事汇总
  20. 命令提示符的三种打开方式

热门文章

  1. Android4.0图库Gallery2代码分析(二) 数据管理和数据加载
  2. 使用nohup在后台运行scp
  3. 牛客 - 牛半仙的妹子Tree(按询问分块+RMQ求LCA)
  4. java e.getmessage() null_Java e.getMessage 错误信息为null
  5. 每一个正整数可以表示为3个三角形数之和
  6. SPOJ1811最长公共子串问题(后缀自动机)
  7. POJ2352 stars(树状数组)
  8. 进程隐藏与进程保护(SSDT Hook 实现)(三)
  9. 对现有的所能找到的DDOS代码(攻击模块)做出一次分析----自定义攻击篇
  10. 秒杀多线程第八篇 经典线程同步 信号量Semaphore