nginx事件模塊 -- 第五篇 epoll add

微信公衆號:鄭爾多斯
關注可瞭解更多的Nginx知識。任何問題或建議,請公衆號留言;
關注公衆號,有趣有內涵的文章第一時間送達!微信

內容回顧

上一篇文章咱們介紹了Nginxepoll初始化過程。從這一篇文章開始咱們繼續介紹ngx_epoll_module的源碼,包括添加事件,刪除事件,觸發事件等。app

ngx_epoll_module_ctx源碼

 1static ngx_event_module_t  ngx_epoll_module_ctx = {
2    &epoll_name,
3    ngx_epoll_create_conf,               /* create configuration */
4    ngx_epoll_init_conf,                 /* init configuration */
5
6    {
7        ngx_epoll_add_event,             /* add an event */
8        ngx_epoll_del_event,             /* delete an event */
9        ngx_epoll_add_event,             /* enable an event */
10        ngx_epoll_del_event,             /* disable an event */
11        ngx_epoll_add_connection,        /* add an connection */
12        ngx_epoll_del_connection,        /* delete an connection */
13#if (NGX_HAVE_EVENTFD)
14        ngx_epoll_notify,                /* trigger a notify */
15#else
16        NULL,                            /* trigger a notify */
17#endif
18        ngx_epoll_process_events,        /* process the events */
19        ngx_epoll_init,                  /* init the events */
20        ngx_epoll_done,                  /* done the events */
21    }
22};
複製代碼

添加新事件

從上面的源碼中咱們能夠知道,epoll添加事件的方法爲ngx_epoll_add_event,源碼以下:函數

 1static ngx_int_t
2ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
3
{
4    int                  op;
5    uint32_t             events, prev;
6    ngx_event_t         *e;
7    ngx_connection_t    *c;
8    struct epoll_event   ee;
9
10    c = ev->data;
11
12    events = (uint32_t) event;
13
14    if (event == NGX_READ_EVENT) {
15        e = c->write;
16        prev = EPOLLOUT;
17#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
18        events = EPOLLIN|EPOLLRDHUP;
19#endif
20
21    } else {
22        e = c->read;
23        prev = EPOLLIN|EPOLLRDHUP;
24#if (NGX_WRITE_EVENT != EPOLLOUT)
25        events = EPOLLOUT;
26#endif
27    }
28
29    if (e->active) {
30        op = EPOLL_CTL_MOD;
31        events |= prev;
32
33    } else {
34        op = EPOLL_CTL_ADD;
35    }
36
37#if (NGX_HAVE_EPOLLEXCLUSIVE && NGX_HAVE_EPOLLRDHUP)
38    if (flags & NGX_EXCLUSIVE_EVENT) {
39        events &= ~EPOLLRDHUP;
40    }
41#endif
42
43    ee.events = events | (uint32_t) flags;
44    ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
45
46    if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
47        return NGX_ERROR;
48    }
49
50    ev->active = 1;
51    return NGX_OK;
52}
複製代碼

該函數的三個參數功能以下:ui

ev:咱們要添加的事件
event: 事件的類型,讀事件或者寫事件,咱們這裏分析read event,對於write event來講道理相同
flags: 添加事件的參數spa

咱們這裏只分析read event:
這裏有一個問題,爲何添加read event的時候要判斷c->write呢?3d

1 if (event == NGX_READ_EVENT) {
2        e = c->write;
3        prev = EPOLLOUT;
4#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
5        events = EPOLLIN|EPOLLRDHUP;
6#endif
7}
複製代碼

其實結合後面的代碼就很清楚了,咱們看一下後面的代碼:code

1if (e->active) {
2        op = EPOLL_CTL_MOD;
3        events |= prev;
4else {
5        op = EPOLL_CTL_ADD;
6}
複製代碼

由於往epoll中增長事件的時候,有兩種方式,分別爲 addmodify。當咱們將某個fd添加read event的時候,若是該fdwrite event已經被添加到了epoll中,那麼咱們就不能繼續add了,只能modify,因此這裏要先判斷一下write event的狀態。
咱們查看 man epoll手冊,在Question and answers部分有下面一個Question,以下:orm

Q1 What happens if you register the same file descriptor on an epoll instance twice?
A1 You will probably get EEXIST. However, it is possible to add a duplicate (dup(2), dup2(2), fcntl(2) F_DUPFD) descriptor to tcdn

這裏有一點要注意,那就是咱們添加的eventdata字段,咱們先看一下epoll函數中event的結構:事件

 1 typedef union epoll_data {
2     void        *ptr;
3     int          fd;
4     uint32_t     u32;
5     uint64_t     u64;
6epoll_data_t;
7
8struct epoll_event {
9    uint32_t     events;      /* Epoll events */
10    epoll_data_t data;        /* User data variable */
11};
複製代碼

ngx_epoll_add_event()函數中有下面一句話:

1ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
複製代碼

這裏會把 event->data->ptr指向當前事件對應的connection。這是一個很重要的特性。這樣的話,當咱們epoll_wait()獲取到某個事件以後,就能夠拿到這個事件對應的connection,而後進行各類操做。

這就是ngx_epoll_add_event()的處理流程,這裏遺留了一個問題:
read event 或者 write eventdata字段是何時指向了connection呢?
實際上是在 ngx_get_connection()方法中。咱們隨後會分析這個函數。


喜歡本文的朋友們,歡迎長按下圖關注訂閱號鄭爾多斯,更多精彩內容第一時間送達

鄭爾多斯
鄭爾多斯
相關文章
相關標籤/搜索