redis源码笔记-ae_epoll.c
这部分代码是具体事件触发网络库的底层实现。Linux下有epoll设施,而且其效率是现在最高的。注意即使高效如redis,其也只是选择了自动档-水平触发(自动档和手动档的典故请自行google)。据说libevent也是使用的水平触发。废话不多说,看代码吧。
1 #include <sys/epoll.h> 2 3 typedef struct aeApiState { 4 int epfd; 5 struct epoll_event events[AE_SETSIZE]; //存的是epoll_wait返回后得到的事件列表 6 } aeApiState; //作为eventLoop结构的apidata存储 7 8 static int aeApiCreate(aeEventLoop *eventLoop) { 9 aeApiState *state = zmalloc(sizeof(aeApiState)); 10 11 if (!state) return -1; 12 state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */ 13 if (state->epfd == -1) return -1; 14 eventLoop->apidata = state; 15 return 0; 16 } 17 18 static void aeApiFree(aeEventLoop *eventLoop) { 19 aeApiState *state = eventLoop->apidata; 20 21 close(state->epfd); 22 zfree(state); 23 } 24 25 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { 26 aeApiState *state = eventLoop->apidata; 27 struct epoll_event ee; 28 /* If the fd was already monitored for some event, we need a MOD 29 * operation. Otherwise we need an ADD operation. */ 30 int op = eventLoop->events[fd].mask == AE_NONE ? 31 EPOLL_CTL_ADD : EPOLL_CTL_MOD; 32 33 ee.events = 0; 34 mask |= eventLoop->events[fd].mask; /* Merge old events */ 35 if (mask & AE_READABLE) ee.events |= EPOLLIN; 36 if (mask & AE_WRITABLE) ee.events |= EPOLLOUT; 37 ee.data.u64 = 0; /* avoid valgrind warning */ 38 ee.data.fd = fd; 39 if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1; 40 return 0; 41 } 42 43 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) { 44 aeApiState *state = eventLoop->apidata; 45 struct epoll_event ee; 46 int mask = eventLoop->events[fd].mask & (~delmask); 47 48 ee.events = 0; 49 if (mask & AE_READABLE) ee.events |= EPOLLIN; 50 if (mask & AE_WRITABLE) ee.events |= EPOLLOUT; 51 ee.data.u64 = 0; /* avoid valgrind warning */ 52 ee.data.fd = fd; 53 if (mask != AE_NONE) { 54 epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee); 55 } else { 56 /* Note, Kernel < 2.6.9 requires a non null event pointer even for 57 * EPOLL_CTL_DEL. */ 58 epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee); 59 } 60 } 61 62 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) { 63 aeApiState *state = eventLoop->apidata; 64 int retval, numevents = 0; 65 66 retval = epoll_wait(state->epfd,state->events,AE_SETSIZE, 67 tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1); 68 if (retval > 0) { 69 int j; 70 71 numevents = retval; 72 for (j = 0; j < numevents; j++) { 73 int mask = 0; 74 struct epoll_event *e = state->events+j; 75 76 if (e->events & EPOLLIN) mask |= AE_READABLE; 77 if (e->events & EPOLLOUT) mask |= AE_WRITABLE; 78 eventLoop->fired[j].fd = e->data.fd; 79 eventLoop->fired[j].mask = mask;
//在fired数组里注册 80 } 81 } 82 return numevents; 83 } 84 85 static char *aeApiName(void) { 86 return "epoll"; 87 }