Redis事件管理(三)
生活随笔
收集整理的這篇文章主要介紹了
Redis事件管理(三)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?Redis的事件管理和定時器的管理都是自己來實現的,Redis的事件管理分為兩部分,一部分是封裝了系統的異步事件API,還有一部分是在這基礎上封裝了一個通用的事件管理器,根據具體的系統來決定具體使用哪個異步管理API。
先來說說Redis支持哪些異步的系統API。Redis內部封裝了epoll,evport,kqueue,select這四個原始的事件管理器。
那epoll舉個例子解析一下吧。
1 typedef struct aeApiState 2 { 3 int epfd; //文件描述符 4 struct epoll_event *events;//epoll實例 5 } aeApiState;這個結構體封裝了一個具體的事件實例。
封裝的接口函數:
1 static int aeApiCreate(aeEventLoop *eventLoop) //創建一個事件管理器 2 static int aeApiResize(aeEventLoop *eventLoop, int setsize) //重置事件管理器管理事件的個數 3 static void aeApiFree(aeEventLoop *eventLoop) //刪除一個事件管理器 4 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)//向事件管理器中添加一個事件 5 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) //從時間管理器中刪除一個事件 6 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)//激活事件管理器,返回已經觸發的事件的個數 7 static char *aeApiName(void) //獲取當前使用的是什么事件模型 1 static int aeApiCreate(aeEventLoop *eventLoop) //創建一個事件管理器 1 /*創建成功返回0,否則返回-1*/ 2 static int aeApiCreate(aeEventLoop *eventLoop) 3 { 4 aeApiState *state = zmalloc(sizeof(aeApiState)); 5 6 if (!state) return -1; 7 /*直接按size申請內存*/ 8 state->events = zmalloc(sizeof(struct epoll_event) * eventLoop->setsize); 9 /*事件內存失敗時要釋放結構體的內存,防止出現內存泄露*/ 10 if (!state->events) 11 { 12 zfree(state); 13 return -1; 14 } 15 /*創建epoll描述符,如果創建失敗,記得把上面申請的內存釋放掉*/ 16 state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */ 17 if (state->epfd == -1) 18 { 19 zfree(state->events); 20 zfree(state); 21 return -1; 22 } 23 eventLoop->apidata = state; 24 return 0; 25 } 2 static int aeApiResize(aeEventLoop *eventLoop, int setsize) //重置事件管理器管理事件的個數 /*重置可接受事件的個數,這個函數不能直接調用,因為沒有檢查新size和舊size的大小關系,如果小了,直接重置會出問題*/ static int aeApiResize(aeEventLoop *eventLoop, int setsize) {aeApiState *state = eventLoop->apidata;state->events = zrealloc(state->events, sizeof(struct epoll_event)*setsize);return 0; } 4 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)//向事件管理器中添加一個事件 1 /*向epoll中增加事件,需要注冊新的文件描述符和需要監控的事件類型*/ 2 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) 3 { 4 aeApiState *state = eventLoop->apidata; 5 struct epoll_event ee; 6 /*因為epoll的維護是用數組維護的,通過下標的方式可以直接訪問,省時省力。如果這個節點已經激活了,那新事件添加就好了*/ 7 int op = eventLoop->events[fd].mask == AE_NONE ? EPOLL_CTL_ADD : EPOLL_CTL_MOD; 8 9 ee.events = 0; 10 mask |= eventLoop->events[fd].mask; /* Merge old events */ 11 if (mask & AE_READABLE) ee.events |= EPOLLIN; 12 if (mask & AE_WRITABLE) ee.events |= EPOLLOUT; 13 ee.data.u64 = 0; /* avoid valgrind warning */ 14 ee.data.fd = fd; 15 if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1; 16 return 0; 17 } 6 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)//激活事件管理器,返回已經觸發的事件的個數 /*獲取事件隊列*/ static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {aeApiState *state = eventLoop->apidata;int retval, numevents = 0;retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);if (retval > 0) {int j;numevents = retval;/*將滿足條件的文件描述符和狀態保存到fired中,后期逐個處理*/for (j = 0; j < numevents; j++) {int mask = 0;struct epoll_event *e = state->events+j;if (e->events & EPOLLIN) mask |= AE_READABLE;if (e->events & EPOLLOUT) mask |= AE_WRITABLE;if (e->events & EPOLLERR) mask |= AE_WRITABLE;if (e->events & EPOLLHUP) mask |= AE_WRITABLE;eventLoop->fired[j].fd = e->data.fd;eventLoop->fired[j].mask = mask;}}return numevents; }?
轉載于:https://www.cnblogs.com/likui360/p/5297729.html
總結
以上是生活随笔為你收集整理的Redis事件管理(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaweb数据库操作
- 下一篇: MySQL 数据库 InnoDB 和 M