Event Handle File Event - wyc902/redis GitHub Wiki

通过aeProcessEvents函数我们知道redis server会优先处理文件事件,根据掩码来区分事件是读还是写,然后调用事件创建时候绑定好的函数处理。

    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);
    }

创建文件事件的函数是

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData) {
    aeFileEvent *fe = &eventLoop->events[fd];

    if (aeApiAddEvent(eventLoop, fd, mask) == -1)
        return AE_ERR;
    fe->mask |= mask;
    if (mask & AE_READABLE) fe->rfileProc = proc;
    if (mask & AE_WRITABLE) fe->wfileProc = proc;
    fe->clientData = clientData;
    if (fd > eventLoop->maxfd)
        eventLoop->maxfd = fd;
    return AE_OK;
}

这个函数会传入处理函数的指针,clientData指向一片内存区域,里面存放结构化的要发给客户端的数据或者从客户端接收来的数据。 由于底层的io多路复用模块不同,可以是select,epoll,kqueue等。redis使用eventLoop->aeFiredEvent数组存放已经ready的事件,只要是在这个数组里的事件io已完成可以直接被相关处理函数处理,从而屏蔽底层os实现的不同。

for (j = 0; j < numevents; j++) {
    aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
    ......
    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++;
}