ngx事件驱动机制

来源:互联网 发布:淘宝小号挂机赚钱 编辑:程序博客网 时间:2024/04/29 13:05
事件驱动机制nginx中事件驱动机制涉及到的模块很清晰,linux中为ngx_event_modulengx_event_core_modulengx_epoll_module三个模块。其中ngx_event_module负责解析event{}中的配置,并且调度其它两个模块。ngx_event_core_module负责调度epoll模块(use配置字段)epoll模块负责具体的事件处理ngx_event.c文件中。定义的ngx_event_modulengx_event_core_modulengx_module_t ngx_event_module = {.....;    &ngx_events_module_ctx; ngx_events_commands;    .....;    NULL    .....;}ngx_events_moudle_ctx上下文没有create_conf函数。ngx_events_commands中有一个解析命令函数。ngx_events_commands []={   { ngx_string(“event”);  NGX_MAIN_CONF|...;     ngx_events_block;     0.      ...     }}即这个ngx_event_block函数,这个函数在ngx_init_cycle函数中解析配置文件时候调用ngx_conf_parse时,遇到“event”字样的时候,被调用的。该函数用于解析event{}中所有的配置。1,创建配置指针放入cycle->ctx数组中。2,调用所有事件模块(这里一般就两个event_coreepoll)   create_conf创建各自需要的配置结构体3,开始解析event{}中的所有配置,4,调用所有事件模块的init_conf为各个事件模块的配置结构体   做最后的赋值.(其实也只有两个,即上面的两个)基本上ngx_event_moudle的工作就全部在ngx_event_block中了。再看ngx_event_core_modulengx_module_t ngx_event_core_module = {   NGX_MODULE_V1,&ngx_event_core_module_ctx,ngx_event_core_commands,   ...,ngx_event_module_init,ngx_event_process_init, ...,}ngx_event_module不同的是,它里面已经有很多回调函数了按照顺序的调用,看看函数的调用顺序。先看它的上下文ngx_event_module_t ngx_event_core_module_ctx = {&event_core_name,ngx_event_create_conf,ngx_event_init_conf,}因为在ngx_event_block中会回调这里的create_conf函数的(当然,同时回调的还有epoll模块的create_conf,这里暂且不看)ngx_event_create_conf函数的工作:当然主要是生成配置结构体ngx_event_conf_t类型,这个是存放event{}中的各个字段的。配置结构体生成后,接着是解析event{}中的配置了这其中就会调用到很多ngx_event_core_modulecommands中的set函数。具体有ngx_event_connections,ngx_event_use,ngx_conf_set_flag_slot,ngx_conf_set_flag_slot,ngx_event_debug_connection,这些函数都从配置中把数据存放在生成的配置结构体中。接着的函数是init_conf了,也即完成配置结构体的赋值。。走到这里,以event{}驱动的地方就完成了。然后是ngx_event_core_moudle模块的初始化函数ngx_event_module_init(在ngx_init_cycle中调用的,当时是对整个模块数组都调用这个函数,不过没几个模块实现了这个方法)这个函数起始没做多少事情,它主要初始化了一些变量,尤其是ngx_http_stub_status_module统计模块使用的一些原子性的统计变量。接着,前面都都是在master进程中完成的,下面fork出子进程之后,在子进程的ngx_worker_process_cycle(这个是子进程的执行函数)ngx_worker_process_cycle->ngx_worker_process_init后面的这个函数会一次调用每个模块的init_process方法。这时候ngx_event_core_module模块的init_process方法就被回调了(也即ngx_event_process_init)(好像只有这个模块才实现了这个方法)ngx_event_process_init这个函数完成了大部分的事件驱动机制的初始化工作,也是在这个函数中连接到了epoll模块中去。这里要回顾一下前面的ngx_event_block因为在此函数中调用了epoll模块的create_conf函数。那么先来看看epoll模块的定义ngx_module_t ngx_epoll_module={  NGX_MOUDLE_V1,  &ngx_epoll_module_ctx,ngx_epoll_commands;   .....;}看看ctxngx_event_module_t ngx_epoll_module_ctx ={   &epoll_name,ngx_epoll_create_conf,ngx_epoll_init_conf,   {ngx_epoll_add_event,ngx_epoll_del_event,....;ngx_epoll_add_connection,ngx_epoll_del_connection,NULL,ngx_epoll_process_events,    ngx_epoll_init, ngx_epoll_done,     },}所有,这里先create_conf,很简单,创建epoll模块管理的配置结构体ngx_epoll_conf_t类型。回到ngx_event_process_init中。 1,调用use配置项指定的事件驱动模块的init方法    这里假设调用epoll模块中的action.init方法。    module->actions.initinit即为ngx_epoll_init函数。这里先看看这个函数,因为对下面的有引用   ngx_epoll_init做了两件事    1,调用epoll_create创建了epoll对象 2,创建evet_list数组,用于进行epoll_wait调用时传递到内核态的事件并且,在这里还初始化了几个全局变量,其中较为重要的   ngx_event_actions=ngx_epoll_module_ctx.atcions   即把ngx_event_actions指明为epollactions这样以后就很方便的引用事件操作方法了而且,还设计了宏定义    #define ngx_add_event   ngx_event_actions.add #define ngx_del_eventngx_event_actions.del #define ngx_add_connngx_event_actions.add_conn....  更加方便同一了。 2,分配连接池,读事件,写事件,并把它们想关联起来。 3,为listening套接子获取连接池(有可能很几个监听套接子同时在监听),这样每个监听套接子就有了相应的读写事件域(因为和connection关联的),并设置其读事件的方法为ngx_event_accept方法。此方法不属于任何模块,是单独的。4,将监听连接的事件添加到事件驱动模块中即调用了ngx_add_event方法。到这里,ngx_event_process_init方法基本完成,即驱动机制初始化完成。下面就是利用驱动机制开始处理事件了。要回到子进程中去。(ngx_worker_process_cycle)ngx_worker_process_init子进程初始化完了后,有一个for循环 ,主要是分发、处理事件。其核心就是ngx_process_events_and_timers方法。该函数是事件驱动机制的核心,比较复杂。其主要操作有31,调用所使用的事件驱动模块实现的process_event方法,处理网络事件  (如果这里是epoll模块的话,那么这个process_event方法就是ngx_event_actions.process_events也即ngx_epoll_process_events方法。2,处理两个post事件队列中的事件   ngx_event_process_posted(cycle,&ngx_posted_accept_events);ngx_event_process_posted(cycle,&ngx_posted_events);3,处理定时器事件,ngx_event_expire_timers;还有一个重点没有涉及到的即ngx_event_accept方法,用来建立新连接的在上面有讲到过,它被注册为监听套接子 读事件的处理方法
0 0
原创粉丝点击