事件循环这个概念貌似在windows编程中提得更多,Linux程序却很少提及这个概念。本文所提及的事件循环其实就是worker cycle,由于此处将关注的不再是worker进程,而是worker进程在循环过程中关于事件处理的环节,因此就盗用了事件循环这个概念。在具体看代码前,先看一下这个“循环”的概貌:
经过前面相关博文的介绍,我们了解到master进程创建好一个worker进程后,worker进程还会进行一个初始化工作,然后才会陷入“死”循环中。这个“死循环”也就是本文将谈及的事件循环,也就是上图中的黄色部分。整个黄色部份是由一个循环构成的,实际上,这个循环里将会做很多的事情,但本文将只关注图中红色标注的事件部分——ngx_process_events_and_timers。ngx_process_events_and_timers是一个函数(定义在src/event/ngx_event.c中)。接下来,就从这个函数开始进入事件驱动的核心。
ngx_process_events_and_timers一做完工作,就又回到了事件循环中去了,上图示;但会很快又会回到事件处理中来。
上文中,分析了事件循环中有关事件处理的过程;在分析的过程中,我们有提到对accept事件的处理,accept事件就是监听套接口上有新的连接到来的事件;接下来,我们分析一下accept事件的handler方法,看看accept事件的处理过程是如何的。accept事件的handler方法是ngx_event_accept(位于src/event/ngx_event_accept.c中),代码分析如下:
- void
- ngx_event_accept(ngx_event_t *ev)
- {
- socklen_t socklen;
- ngx_err_t err;
- ngx_log_t *log;
- ngx_socket_t s;
- ngx_event_t *rev, *wev;
- ngx_listening_t *ls;
- ngx_connection_t *c, *lc;
- ngx_event_conf_t *ecf;
- u_char sa[NGX_SOCKADDRLEN];
- 。。。。。。。。。。。。。。。。。
-
- lc = ev->data;
- ls = lc->listening;
- ev->ready = 0;
- do {
- socklen = NGX_SOCKADDRLEN;
-
- s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
-
- if (s == -1) {
- err = ngx_socket_errno;
- if (err == NGX_EAGAIN) {
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err,
- "accept() not ready");
- return;
- }
- ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
- NGX_LOG_ERR : NGX_LOG_ALERT),
- ev->log, err, "accept() failed");
- if (err == NGX_ECONNABORTED) {
- if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
- ev->available--;
- }
- if (ev->available) {
- continue;
- }
- }
- return;
- }
-
-
-
-
-
-
-
-
-
- ngx_accept_disabled = ngx_cycle->connection_n / 8
- - ngx_cycle->free_connection_n;
-
- c = ngx_get_connection(s, ev->log);
- if (c == NULL) {
- if (ngx_close_socket(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
- return;
- }
-
- c->pool = ngx_create_pool(ls->pool_size, ev->log);
- if (c->pool == NULL) {
- ngx_close_accepted_connection(c);
- return;
- }
- 。。。。。。。。。。。。。。
-
- if (ngx_inherited_nonblocking) {
- if (ngx_event_flags & NGX_USE_AIO_EVENT) {
- if (ngx_blocking(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
- ngx_blocking_n " failed");
- ngx_close_accepted_connection(c);
- return;
- }
- }
- } else {
-
- if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
- if (ngx_nonblocking(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
- ngx_nonblocking_n " failed");
- ngx_close_accepted_connection(c);
- return;
- }
- }
- }
- *log = ls->log;
-
- c->recv = ngx_recv;
- c->send = ngx_send;
- c->recv_chain = ngx_recv_chain;
- c->send_chain = ngx_send_chain;
- c->log = log;
- c->pool->log = log;
- c->socklen = socklen;
- c->listening = ls;
- c->local_sockaddr = ls->sockaddr;
- c->local_socklen = ls->socklen;
- c->unexpected_eof = 1;
- rev = c->read;
- wev = c->write;
- wev->ready = 1;
- if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
-
- rev->ready = 1;
- }
- if (ev->deferred_accept) {
- rev->ready = 1;
- }
- rev->log = log;
- wev->log = log;
-
-
-
-
-
-
-
-
- c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
- 。。。。。。。。。。。。。。。。。。。
- if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
- if (ngx_add_conn(c) == NGX_ERROR) {
- ngx_close_accepted_connection(c);
- return;
- }
- }
- log->data = NULL;
- log->handler = NULL;
-
-
-
-
-
- ls->handler(c);
- if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
- ev->available--;
- }
- } while (ev->available);
- }
accept事件的handler方法也就是如此了。accept中调用的handler是ngx_http_init_connection函数。
本文摘自:http://blog.csdn.net/Marcky/article/details/6025651感谢作者
阅读(2976) | 评论(0) | 转发(0) |