Redis源碼閱讀之: 事件模型ae

源碼文件

  • src/ae.c

入口函數

  • 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.ciocp版的實現
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 確保讀/寫事件只能執行其中一個
                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的文件事件---> 獲取事件---> 執行事件回調
  • 剩下具體細節不多贅述, 順着思路看源碼即可

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章