redis的网络模型处理的fd必须小于2048(在events结构体中放不下);
/* State of an event based program */
typedef struct aeEventLoop {
int maxfd;
long long timeEventNextId;
aeFileEvent events[AE_SETSIZE]; /* Registered events */
aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
aeTimeEvent *timeEventHead;
int stop;
void *apidata; /* This is used for polling API specific data */
aeBeforeSleepProc *beforesleep;
} aeEventLoop;
/* File event structure */
typedef struct aeFileEvent {
int mask; /* one of AE_(READABLE|WRITABLE) */
aeFileProc *rfileProc;
aeFileProc *wfileProc;
void *clientData;
} aeFileEvent;
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
/* A fired event */
typedef struct aeFiredEvent {
int fd;
int mask;
} aeFiredEvent;
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData);
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
将fd交给eventloop托管,直接通过aeEventLoop.events[fd]找到托管aeFileEvent;
每个fd关联一个mask(托管事件readable or writable),读函数(可读时调用)和写函数(可写时调用),以及clientData(传给读写函数);
aeFireEvent类似epoll的epoll_event;
首先,通过epoll_wait拿到events,再转存到fired数组中;
通过fired数组中的fd找到托管的aeFileEvent,获得读函数、写函数及clientData,然后,根据fired数组中的mask调用读写函数;
之所以引入aeFireEvent,是因为redis的网络模型不仅仅支持epoll,还支持select和kqueue,需要一个中间抽象层;
除了托管fd外,还支持timer,timer都存储在链表timeEventHead,每轮poll后,会check一下timer;