redis中io复用之epoll

本文详细介绍了epoll在Redis中的具体应用过程,包括通过epoll_create创建文件描述符,使用epoll_ctl添加或删除事件监听,以及利用epoll_wait等待事件的发生等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面讲过evport的实现,下来我们继续看看我们epoll在redis中的使用
1:首先通过epoll_create 来新建fd
例如:
typedef struct aeApiState {
    int epfd;
    struct epoll_event *events;
} aeApiState;
static int aeApiCreate(aeEventLoop *eventLoop) {
    aeApiState *state = zmalloc(sizeof(aeApiState));

    if (!state) return -1;
    #为要监控的event申请空间
    state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);
    if (!state->events) {
        zfree(state);
        return -1;
    }
    #通过epoll_create来新建1024个fd来提供给系统使用
    state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */
    if (state->epfd == -1) {
        zfree(state->events);
        zfree(state);
        return -1;
    }
    eventLoop->apidata = state;
    return 0;
}
2:通过epoll_ctl来add/del event
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
    aeApiState *state = eventLoop->apidata;
    struct epoll_event ee;
    /* If the fd was already monitored for some event, we need a MOD
     * operation. Otherwise we need an ADD operation. */
    #这里的op表示是添加event还是修改已经存在的event
    int op = eventLoop->events[fd].mask == AE_NONE ?
            EPOLL_CTL_ADD : EPOLL_CTL_MOD;

    ee.events = 0;
    mask |= eventLoop->events[fd].mask; /* Merge old events */
    #监控读和写事件
    if (mask & AE_READABLE) ee.events |= EPOLLIN;
    if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
    ee.data.u64 = 0; /* avoid valgrind warning */
    #要监控的fd
    ee.data.fd = fd;
    #将前面设置好的epfd/op/fd/ee 通过epoll_ctl 设置到kernel space
    if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;
    return 0;
}
3:最后通过epoll_wait 来等待event时间的发生。
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
    aeApiState *state = eventLoop->apidata;
    int retval, numevents = 0;
    #通过epoll_wait 等待epfd事件的发生,这里有设置timeout的时间,在规定的时间内epoll_wait 必须返回
    retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,
            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);
    #retval大于0说明是有event发生了,如果是timeout返回则retval等于-1
    if (retval > 0) {
        int j;

        numevents = retval;
        #遍历state->events 数据分别找出是读还是写event
        for (j = 0; j < numevents; j++) {
            int mask = 0;
            struct epoll_event *e = state->events+j;
	    #根据mask 判断是读还是写事件
            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;
	    #保持发生event的fd和保存fd对于的mask
            eventLoop->fired[j].fd = e->data.fd;
            eventLoop->fired[j].mask = mask;
        }
    }
    return numevents;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值