您的位置:首页 > 数据库 > Redis

redis中io复用之evport

2018-03-05 09:46 1301 查看
从redis中的ae.c中可以知道目前复用io的方式有下面四种
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
#ifdef HAVE_EPOLL
#include "ae_epoll.c"
#else
#ifdef HAVE_KQUEUE
#include "ae_kqueue.c"
#else
#include "ae_select.c"
#endif
#endif
#endif
即复用io的四种方式分别是evport->epoll->kqueue->select。其执行的效率也是从高到低
我们首先看看evport是如何使用的。evport的实现在ae_evport.c中
其使用的步骤如下:
1:首先通过port_create() 来申请一个port
static int aeApiCreate(aeEventLoop *eventLoop) {
int i;
#申请结构体
aeApiState *state = zmalloc(sizeof(aeApiState));
if (!state) return -1;
#通过port_create() 来申请一个port
state->portfd = port_create();
if (state->portfd == -1) {
zfree(state);
return -1;
}

return 0;
}
2:通过port_assocoate关联要要监控的fd
static int aeApiAssociate(const char *where, int portfd, int fd, int mask) {
int events = 0;
int rv, err;
#从这里知道目前只有读和写这两个事件
if (mask & AE_READABLE)
events |= POLLIN;
if (mask & AE_WRITABLE)
events |= POLLOUT;

#通过port_assocoate关联要要监控的fd
rv = port_associate(portfd, PORT_SOURCE_FD, fd, events,
(void *)(uintptr_t)mask);

return rv;
}
2:通过port_getn开始监控fd的io事件
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
aeApiState *state = eventLoop->apidata;
struct timespec timeout, *tsp;
int mask, i;
uint_t nevents;
port_event_t event[MAX_EVENT_BATCHSZ];

nevents = 1;
if (port_getn(state->portfd, event, MAX_EVENT_BATCHSZ, &nevents,
tsp) == -1 && (errno != ETIME || nevents == 0)) {
if (errno == ETIME || errno == EINTR)
return 0;

/* Any other error indicates a bug. */
perror("aeApiPoll: port_get");
abort();
}

state->npending = nevents;
#port_getn正常返回,表示监控到了io的read或者write事件
for (i = 0; i < nevents; i++) {
mask = 0;
#根据返回event中的flag来区分是读事件还是写事件
if (event[i].portev_events & POLLIN)
mask |= AE_READABLE;
if (event[i].portev_events & POLLOUT)
mask |= AE_WRITABLE;
#更新eventLoop 中监控到的io事件中的fd和mask
eventLoop->fired[i].fd = event[i].portev_object;
eventLoop->fired[i].mask = mask;

}

return nevents;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: