redis源码阅读之ae_kqueue

4870阅读 0评论2019-06-16 stolennnxb
分类:NOSQL

kqueue是FreeBSD当中提供的io多路复用机制,由于上一篇在介绍epoll()的时候被告知有敏感词,不让发,那kqueue()的具体介绍也就只能往后延一下了,这里着重介绍redis是如何包装的

点击(此处)折叠或打开

  1. typedef struct aeApiState {
  2.     int kqfd;
  3.     struct kevent *events;
  4. } aeApiState;
其一般的api调用如下:

点击(此处)折叠或打开

  1. static int aeApiCreate(aeEventLoop *eventLoop) {
  2.     aeApiState *state = zmalloc(sizeof(aeApiState));

  3.     if (!state) return -1;
  4.     state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize);
  5.     if (!state->events) {
  6.         zfree(state);
  7.         return -1;
  8.     }
  9.     state->kqfd = kqueue();
  10.     if (state->kqfd == -1) {
  11.         zfree(state->events);
  12.         zfree(state);
  13.         return -1;
  14.     }
  15.     eventLoop->apidata = state;
  16.     return 0;
  17. }

  18. static int aeApiResize(aeEventLoop *eventLoop, int setsize) {
  19.     aeApiState *state = eventLoop->apidata;

  20.     state->events = zrealloc(state->events, sizeof(struct kevent)*setsize);
  21.     return 0;
  22. }

  23. static void aeApiFree(aeEventLoop *eventLoop) {
  24.     aeApiState *state = eventLoop->apidata;

  25.     close(state->kqfd);
  26.     zfree(state->events);
  27.     zfree(state);
  28. }

  29. static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
  30.     aeApiState *state = eventLoop->apidata;
  31.     struct kevent ke;

  32.     if (mask & AE_READABLE) {
  33.         EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
  34.         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
  35.     }
  36.     if (mask & AE_WRITABLE) {
  37.         EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
  38.         if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1;
  39.     }
  40.     return 0;
  41. }

  42. static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {
  43.     aeApiState *state = eventLoop->apidata;
  44.     struct kevent ke;

  45.     if (mask & AE_READABLE) {
  46.         EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
  47.         kevent(state->kqfd, &ke, 1, NULL, 0, NULL);
  48.     }
  49.     if (mask & AE_WRITABLE) {
  50.         EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
  51.         kevent(state->kqfd, &ke, 1, NULL, 0, NULL);
  52.     }
  53. }
  54. static char *aeApiName(void) {
  55.     return "kqueue";
  56. }
关键api如下:

点击(此处)折叠或打开

  1. static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
  2.     aeApiState *state = eventLoop->apidata;
  3.     int retval, numevents = 0;

  4.     if (tvp != NULL) {
  5.         struct timespec timeout;
  6.         timeout.tv_sec = tvp->tv_sec;
  7.         timeout.tv_nsec = tvp->tv_usec * 1000;
  8.         retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
  9.                         &timeout);
  10.     } else {
  11.         retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize,
  12.                         NULL);
  13.     }

  14.     if (retval > 0) {
  15.         int j;

  16.         numevents = retval;
  17.         for(j = 0; j < numevents; j++) {
  18.             int mask = 0;
  19.             struct kevent *e = state->events+j;

  20.             if (e->filter == EVFILT_READ) mask |= AE_READABLE;
  21.             if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE;
  22.             eventLoop->fired[j].fd = e->ident;
  23.             eventLoop->fired[j].mask = mask;
  24.         }
  25.     }
  26.     return numevents;
  27. }
还请各位看官老爷多提宝贵意见~
上一篇:redis源码阅读之ae_epoll
下一篇:redis源码阅读之ae_evport