博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis的文件事件
阅读量:5204 次
发布时间:2019-06-13

本文共 5029 字,大约阅读时间需要 16 分钟。

redis的文件事件:即与io相关的事件。

/* File event structure */typedef struct aeFileEvent {    int mask; /* one of AE_(READABLE|WRITABLE) */    aeFileProc *rfileProc; //读网络数据处理函数    aeFileProc *wfileProc; //写网络数据处理函数    void *clientData;} aeFileEvent;

所有的文件事件放在aeEventLoop的数组中:

/* State of an event based program */typedef struct aeEventLoop {    int maxfd;   /* highest file descriptor currently registered */    int setsize; /* max number of file descriptors tracked */    long long timeEventNextId;    time_t lastTime;     /* Used to detect system clock skew */    aeFileEvent *events; /* Registered events */    aeFiredEvent *fired; /* Fired events */    aeTimeEvent *timeEventHead;    int stop;    void *apidata; /* This is used for polling API specific data */    aeBeforeSleepProc *beforesleep;    aeBeforeSleepProc *aftersleep;} aeEventLoop;

重点关注 events数组和fired数组,在(server.c) initServer中创建事件循环,

server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);

在(ae.c) aeCreateEventLoop中,为events数组和fired数组分配内存:

aeEventLoop *aeCreateEventLoop(int setsize) {    aeEventLoop *eventLoop;    int i;    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;    eventLoop->setsize = setsize;    eventLoop->lastTime = time(NULL);    eventLoop->timeEventHead = NULL;    eventLoop->timeEventNextId = 0;    eventLoop->stop = 0;    eventLoop->maxfd = -1;    eventLoop->beforesleep = NULL;    eventLoop->aftersleep = NULL;    if (aeApiCreate(eventLoop) == -1) goto err;    /* Events with mask == AE_NONE are not set. So let's initialize the     * vector with it. */    for (i = 0; i < setsize; i++)        eventLoop->events[i].mask = AE_NONE;    return eventLoop;err:    if (eventLoop) {        zfree(eventLoop->events);        zfree(eventLoop->fired);        zfree(eventLoop);    }    return NULL;}

在aeCreateFileEvent中为events的具体元素赋值,由创建客户端连接进入aeCreateFileEvent方法的调用栈如下:

// 省略其他代码client *createClient(int fd) {    client *c = zmalloc(sizeof(client));    /* passing -1 as fd it is possible to create a non connected client.     * This is useful since all the commands needs to be executed     * in the context of a client. When commands are executed in other     * contexts (for instance a Lua script) we need a non connected client. */    if (fd != -1) {        anetNonBlock(NULL,fd);        anetEnableTcpNoDelay(NULL,fd);        if (server.tcpkeepalive)            anetKeepAlive(NULL,fd,server.tcpkeepalive);        if (aeCreateFileEvent(server.el,fd,AE_READABLE,            readQueryFromClient, c) == AE_ERR)        {            close(fd);            zfree(c);            return NULL;        }    }    ...    return c;}

把rfileProc和wfileProc的值设为readQueryFromClient函数

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,        aeFileProc *proc, void *clientData){    if (fd >= eventLoop->setsize) {        errno = ERANGE;        return AE_ERR;    }    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;}

 

当客户端发生网络IO时:

调用epoll_wait,获取发生事件的文件描述符,设置在fired元素中:

static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {    aeApiState *state = eventLoop->apidata;    int retval, numevents = 0;    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);    if (retval > 0) {        int j;        numevents = retval;        for (j = 0; j < numevents; j++) {            int mask = 0;            struct epoll_event *e = state->events+j;            if (e->events & EPOLLIN) mask |= AE_READABLE;            if (e->events & EPOLLOUT) mask |= AE_WRITABLE;            if (e->events & EPOLLERR) mask |= AE_WRITABLE;            if (e->events & EPOLLHUP) mask |= AE_WRITABLE;            eventLoop->fired[j].fd = e->data.fd;            eventLoop->fired[j].mask = mask;        }    }    return numevents;}

在aeProcessEvents方法中,根据fired元素中的fd,处理IO事件。

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;/* note the fe->mask & mask & ... code: maybe an already processed     * event removed an element that fired and we still didn't     * processed, so we check if the event is still valid. */    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++;}

 

转载于:https://www.cnblogs.com/allenwas3/p/8473312.html

你可能感兴趣的文章
php include_path zendframework
查看>>
C#加快Bitmap的访问速度
查看>>
android 解释dp,px,pt,sp单位
查看>>
《C和指针》读书笔记——第二章 基本概念
查看>>
Acne Diet - Number One FAQ Answered
查看>>
创建型模式之 建造者模式
查看>>
20145302张薇《Java程序设计》实验二报告
查看>>
20145302张薇 《网络对抗技术》 web基础
查看>>
fastjson 的简单使用
查看>>
HighCharts 具体使用及API文档说明
查看>>
201521123023《Java程序设计》第9周学习总结
查看>>
首富王健林励志演讲:《再坚持一会儿》
查看>>
第二次冲刺3
查看>>
acdream.LCM Challenge(数学推导)
查看>>
成员变量与属性的区别
查看>>
利用js对象的特性,去掉数组中的重复项
查看>>
springmvc 类型转换器 数据回显及提示信息
查看>>
蘑菇街2018实习笔试题
查看>>
第五章 基础构建模块
查看>>
[原创]zabbix工具介绍,安装及使用
查看>>