源碼文件
入口函數
src/ae.c
下的void aeMain(aeEventLoop *eventLoop)
函數; 推薦從這個函數開始閱讀
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0;
while (!eventLoop->stop) {
if (eventLoop->beforesleep != NULL)
eventLoop->beforesleep(eventLoop);
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}
}
- 我們着重看下
aeMain
裏面aeProcessEvents(eventLoop, AE_ALL_EVENTS)
做了什麼; 這裏我們留意一下里面的aeApiPoll
函數, 該函數用於獲取可執行的事件
, 獲取之後在下面的for循環中處理事件, 執行事件處理器fe->rfileProc(eventLoop,fd,fe->clientData,mask)
aeApiPoll
函數是ae模塊提供的一個接口, 在ae_epoll.c
ae_kqueue.c
ae_select.c
ae_evport.c
都做了相應的具體實現, 也是所謂IO多路複用
各平臺的具體實現, 目的爲了兼容不同平臺
- 備註: 也許你會好奇爲啥
IO多路複用
沒有iocp
的實現難道windows就沒人權嗎, 其實redis的官方版本是不支持windows的, windows版本在https://github.com/microsoftarchive/redis
由微軟團隊自己維護, 裏面就有ae_wsiocp.c
即iocp
版的實現
int aeProcessEvents(aeEventLoop *eventLoop, int flags) {
... ...
numevents = aeApiPoll(eventLoop, tvp);
for (j = 0; j < numevents; j++) {
aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
int mask = eventLoop->fired[j].mask;
int fd = eventLoop->fired[j].fd;
int rfired = 0;
if (fe->mask & mask & AE_READABLE) {
rfired = 1;
fe->rfileProc(eventLoop,fd,fe->clientData,mask);
}
if (fe->mask & mask & AE_WRITABLE) {
if (!rfired || fe->wfileProc != fe->rfileProc)
fe->wfileProc(eventLoop,fd,fe->clientData,mask);
}
processed++;
}
... ...
}
- 通常說的redis的
reactor模型(反應堆)
其實說的就是aeMain
的大循環中aeProcessEvents
做的那些事情: 監聽網絡連接的FD的文件事件---> 獲取事件---> 執行事件回調
- 剩下具體細節不多贅述, 順着思路看源碼即可
參考