nginx里的epoll与read write事件

epoll原理

n = epoll_wait(epfd,events,20,500);

for(i=0;i<n;++i)

{

c = event_list[i].data.ptr;

c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~3);


/* 连接有可读事件,且该读事件是active活跃的 */

    if ((revents & EPOLLIN) && rev->active) {

     rev = c->read;

     /*
      * 这里要区分active与ready:
      * active是指事件被添加到epoll对象的监控中,
      * 而ready表示被监控的事件已经准备就绪,即可以对其进程IO处理;
      * 读事件的ready代表有数据可以接受处理,写事件的ready代表buffer有空间可写
      */

      rev->ready = 1;

      /*
      * NGX_POST_EVENTS表示已准备就绪的事件需要延迟处理,
      * 根据accept标志位将事件加入到相应的队列中;
      */

      if (flags & NGX_POST_EVENTS) {

           queue = rev->accept ? &ngx_posted_accept_events: &ngx_posted_events;

           ngx_post_event(rev, queue);

       } else {

        /* 若不延迟处理,则直接调用事件的处理函数 */
        rev->handler(rev);
       }

    }

}

// write事件同理

}


每个event在rev→ready设置为1之后,需要进行io处理。

ssize_t

ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)

{

...

for ( ;; ) {

        n = send(c->fd, buf, size, 0);

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,

                       "send: fd:%d %z of %uz", c->fd, n, size);

        if (n > 0) {

            if (n < (ssize_t) size) {

// 发送的数据大小大于0,小于n,说明未发送完成,wev->ready置为0,此次发送结束,下次继续调用write事件进行发送。

                wev->ready = 0;

            }

            c->sent += n;

            return n;

        }
}

...

}


ssize_t

ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)

{

...

do {
        n = recv(c->fd, buf, size, 0);

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,

                       "recv: fd:%d %z of %uz", c->fd, n, size);

        if (n == 0) {

// 无可接受数据,此次读事件结束,ready置0

            rev->ready = 0;

            rev->eof = 1;

}

...

}

每次的读事件,是该fd的读buffer上有数据被写入,引发epollin,如果是水平触发,只要有数据就会一直触发这个读事件,如果是边缘触发,就会等到新的数据被写入才会触发该事件,因此在面对高性能的边缘触发中,一定要注意数据的接收,每次用while true读完,不然一旦有残留,需要等下个包到达才能取出。

每次的写事件很难被触发,因为正常都会被直接发送完成,只有发送一部分数据,写buffer就满了的情况下,epoll会监听该事件,一旦写队列缓冲区有空间,可写,才会触发新的写事件,将数据发送完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值