为什么 Redis 单线程能支撑高并发?( 二 )
这些上下文信息会存储在 eventLoop 的 void *state 中 , 不会暴露到上层 , 只在当前子模块中使用 。
封装 select 函数select 可以监控 FD 的可读、可写以及出现错误的情况 。
在介绍 I/O 多路复用模块如何对 select 函数封装之前 , 先来看一下 select 函数使用的大致流程:
int fd = /* file descriptor */fd_set rfds;FD_ZERO(FD_SET(fd,; ) {select(fd+1,if (FD_ISSET(fd,--tt-darkmode-color: #A3A3A3;">初始化一个可读的 fd_set 集合 , 保存需要监控可读性的 FD;
static int aeApiCreate(aeEventLoop *eventLoop) {aeApiState *state = zmalloc(sizeof(aeApiState));if (!state) return -1;FD_ZERO(FD_ZERO(eventLoop->apidata = http://kandian.youth.cn/index/state;return 0;}
而 aeApiAddEvent 和 aeApiDelEvent 会通过 FD_SET 和 FD_CLR 修改 fd_set 中对应 FD 的标志位:
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {aeApiState *state = eventLoop->apidata;if (maskif (maskreturn 0;}
整个 ae_select 子模块中最重要的函数就是 aeApiPoll , 它是实际调用 select 函数的部分 , 其作用就是在 I/O 多路复用函数返回时 , 将对应的 FD 加入 aeEventLoop 的 fired 数组中 , 并返回事件的个数:
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {aeApiState *state = eventLoop->apidata;int retval, j, numevents = 0;memcpy(memcpy(retval = select(eventLoop->maxfd+1,if (retval > 0) {for (j = 0; j <= eventLoop->maxfd; j++) {int mask = 0;aeFileEvent *fe =if (fe->mask == AE_NONE) continue;if (fe->maskif (fe->maskeventLoop->fired[numevents].fd = j;eventLoop->fired[numevents].mask = mask;numevents++;}}return numevents;}
封装 epoll 函数Redis 对 epoll 的封装其实也是类似的 , 使用 epoll_create 创建 epoll 中使用的 epfd:
static int aeApiCreate(aeEventLoop *eventLoop) {aeApiState *state = zmalloc(sizeof(aeApiState));if (!state) return -1;state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);if (!state->events) {zfree(state);return -1;}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 = http://kandian.youth.cn/index/state;return 0;}
在 aeApiAddEvent 中使用 epoll_ctl 向 epfd 中添加需要监控的 FD 以及监听的事件:
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {aeApiState *state = eventLoop->apidata;struct epoll_event ee = {0}; /* avoid valgrind warning *//* If the fd was already monitored for some event, we need a MOD* operation. Otherwise we need an ADD operation. */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 (maskif (maskee.data.fd = fd;if (epoll_ctl(state->epfd,op,fd,return 0;}
- 都是为自己手机代言,为什么董明珠不行,雷军太行了?
- realme国潮锦鲤手机为什么叫V15?徐起解释命名规则
- 为什么苹果用户哪怕买二手机,都不用安卓?三点原因太真实
- 比原子弹还稀有,全球就两国掌握,光刻机为什么如此难造?
- 为什么录视频不好看?vivo X60 Pro或许有答案
- 为什么我喜欢C语言,却非常讨厌C++?一位国外程序员的回答
- 为什么说雷军完全凭实力代言小米11?
- 东莞|为什么越来越多的科技人才选择扎根东莞?东莞“引智”的四把钥匙告诉你
- 为什么液晶电视的色温那么高?
- 三星产业这么多,为什么没有像苹果一样做自己的"三星系统"?