Redis 2.8.9源碼 - ae模塊

本文爲做者原創,轉載請註明出處:http://my.oschina.net/fuckphp/blog/505956php

            Redis 的 ae模塊的代碼主要分佈在 ae.c ae.h 還有 ae_*.c 中,分別實現了epoll、evport、kqueue、select幾種網絡模型,本文將以epoll爲例,對Redis的ae模塊進行學習。redis

Redis ae.c 事件模塊筆記

1.ae模塊的核心結構

aeEventLoop

aeEveltLoop 主要定義描述了redis ae模塊的主循環信息,在整個事件的循環週期內(aeEveltLoop.stop!=0),保存了io事件和時間事件的事件列表等信息。
api

typedef struct aeEventLoop {
    int maxfd;   /* 當前註冊的最大描述符 */
    int setsize; /* 最大文件描述符個數 */
    long long timeEventNextId;  //自增id 用於給每一個事件分配id
    time_t lastTime;     /* 用於校準系統時間,每次事件事件執行前更新該時間 */
    aeFileEvent *events; /* 存放註冊的事件 */
    aeFiredEvent *fired; /* 已經觸發的事件保存在這裏 */
    aeTimeEvent *timeEventHead; /* 時間事件單向鏈表 包含了將來將會事件的事件 */
    int stop;
    void *apidata; /* 用戶的自定義數據用於傳遞給回調函數 */
    aeBeforeSleepProc *beforesleep; /* 每個事件循環都會執行一次 */
} aeEventLoop;

aeFileEvent

aeFileEvent 描述了redis ae模塊關於io類事件的主要信息,包含當前事件的讀寫模式回調函數等,註冊一個io事件後aeFileEvent結構被記錄在aeEventLoop的events屬性中,根據文件描述來決定結構在events屬性中的位置
網絡

/* File event structure */
typedef struct aeFileEvent {
    int mask; /* one of AE_(READABLE|WRITABLE) 讀寫模式的定義*/
    aeFileProc *rfileProc; /* 讀操做回調函數的定義 */
    aeFileProc *wfileProc; /* 寫操做回調函數的定義 */
    void *clientData; /* 用戶自定義數據用於傳遞給回調函數 */
} aeFileEvent;

aeTimeEvent

aeTimeEvent 描述了redis時間事件的主要信息,Redis的事件事件結構就是一個鏈表節點,多個時間事件組成鏈表,Redis每一個循環週期會遍歷該鏈表(保存在aeEventLoop.timeEventHead中),進行時間校準後,執行觸發的時間事件。
函數

/* Time event structure */
typedef struct aeTimeEvent {
    long long id; /* 時間事件的id,根據aeEventLoop.timeEventNextId屬性自增來生成 */
    long when_sec; /* 執行當前事件的時間 單位 秒 */
    long when_ms; /* 執行當前事件的時間 單位 毫秒 */
    aeTimeProc *timeProc; /* 事件觸發時候執行 */
    aeEventFinalizerProc *finalizerProc; /* 事件執行完成而且從時間事件鏈表中刪除的時候執行 */
    void *clientData; /* 用戶自定義數據用於傳遞給回調函數 */
    struct aeTimeEvent *next; /* 指向鏈表的下一個節點 */
} aeTimeEvent;

aeFiredEvent

aeFiredEvent 保存了每次被觸發io事件的文件描述符和讀寫模式信息
oop

/* A fired event */
typedef struct aeFiredEvent {
    int fd;    /* 觸發io事件的文件描述符 */
    int mask; /* 描述當前觸發的讀寫模式 */
} aeFiredEvent;

2.ae模塊核心結構之間的關係

該部分使用一張簡單的圖片來表示,具體內容能夠結合上文註釋來理解(圖片偷自 @C_Z 的文章 :) )學習

3.ae模塊執行主流程

建立 aeEventLoop同時初始化 io事件列表和事件事件鏈表和相關的狀態信息,同時建立epoll對象spa

建立 時間事件 設置時間事件觸發的回調函數,執行時間並加入到主循環的timeEventHead鏈表中.net

建立 io事件 根據 設置 epoll監聽的文件表述符描述符讀寫狀態同時更新到aeEventLoop的events事件列表相應位置中(根據文件描述符來定位指針的偏移量)指針

主流流程執行

偷懶。。稍候補圖。。。。

執行 aeBeforeSleepProc 回調函數

讀取最近一個時間事件的距離事件

執行epoll_wait 監聽文件描述符,監聽超時時間截止到下一個時間事件觸發以前或者有io事件觸發

將觸發的io事件放入aeEventLoop.FiredEvent中

讀取觸發的io事件列表並執行對應的讀寫事件

校準系統時間,若是系統時間與lastTime不符合實際狀況,則將時間事件鏈表中全部事件都標記爲當即執行

執行每一一個時間事件的回調函數

根據回調函數返回值決定,當前事件該從時間事件鏈表刪除仍是從新設置下次執行時間

若是時間事件從倆表刪除則執行 aeEventFinalizerProc 回調函數

進入下一個循環週期 知道 aeEventLoop.stop == 0


Redis2.8.9源碼   src/ae.h   src/ae.c     src/ae_epoll.c

相關文章
相關標籤/搜索