當(dāng)前位置:
首頁 >
Redis事件管理(三)
發(fā)布時間:2025/4/9
39
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Redis事件管理(三)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?Redis的事件管理和定時器的管理都是自己來實現(xiàn)的,Redis的事件管理分為兩部分,一部分是封裝了系統(tǒng)的異步事件API,還有一部分是在這基礎(chǔ)上封裝了一個通用的事件管理器,根據(jù)具體的系統(tǒng)來決定具體使用哪個異步管理API。
先來說說Redis支持哪些異步的系統(tǒng)API。Redis內(nèi)部封裝了epoll,evport,kqueue,select這四個原始的事件管理器。
那epoll舉個例子解析一下吧。
1 typedef struct aeApiState 2 { 3 int epfd; //文件描述符 4 struct epoll_event *events;//epoll實例 5 } aeApiState;這個結(jié)構(gòu)體封裝了一個具體的事件實例。
封裝的接口函數(shù):
1 static int aeApiCreate(aeEventLoop *eventLoop) //創(chuàng)建一個事件管理器 2 static int aeApiResize(aeEventLoop *eventLoop, int setsize) //重置事件管理器管理事件的個數(shù) 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)//激活事件管理器,返回已經(jīng)觸發(fā)的事件的個數(shù) 7 static char *aeApiName(void) //獲取當(dāng)前使用的是什么事件模型 1 static int aeApiCreate(aeEventLoop *eventLoop) //創(chuàng)建一個事件管理器 1 /*創(chuàng)建成功返回0,否則返回-1*/ 2 static int aeApiCreate(aeEventLoop *eventLoop) 3 { 4 aeApiState *state = zmalloc(sizeof(aeApiState)); 5 6 if (!state) return -1; 7 /*直接按size申請內(nèi)存*/ 8 state->events = zmalloc(sizeof(struct epoll_event) * eventLoop->setsize); 9 /*事件內(nèi)存失敗時要釋放結(jié)構(gòu)體的內(nèi)存,防止出現(xiàn)內(nèi)存泄露*/ 10 if (!state->events) 11 { 12 zfree(state); 13 return -1; 14 } 15 /*創(chuàng)建epoll描述符,如果創(chuàng)建失敗,記得把上面申請的內(nèi)存釋放掉*/ 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) //重置事件管理器管理事件的個數(shù) /*重置可接受事件的個數(shù),這個函數(shù)不能直接調(diào)用,因為沒有檢查新size和舊size的大小關(guān)系,如果小了,直接重置會出問題*/ 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中增加事件,需要注冊新的文件描述符和需要監(jiān)控的事件類型*/ 2 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) 3 { 4 aeApiState *state = eventLoop->apidata; 5 struct epoll_event ee; 6 /*因為epoll的維護(hù)是用數(shù)組維護(hù)的,通過下標(biāo)的方式可以直接訪問,省時省力。如果這個節(jié)點已經(jīng)激活了,那新事件添加就好了*/ 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)//激活事件管理器,返回已經(jīng)觸發(fā)的事件的個數(shù) /*獲取事件隊列*/ 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;/*將滿足條件的文件描述符和狀態(tài)保存到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; }?
轉(zhuǎn)載于:https://www.cnblogs.com/likui360/p/5297729.html
總結(jié)
以上是生活随笔為你收集整理的Redis事件管理(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaweb数据库操作
- 下一篇: MySQL 数据库 InnoDB 和 M