libevent源码分析--epoll中的几个函数 epoll_init epoll_add epoll_dispatch

来源:互联网 发布:mac 备份照片图库 编辑:程序博客网 时间:2024/06/05 09:10

这篇文件讲解下上面的几篇文章中欠下的几个函数解释。在看这个之前,请移步这篇文章这里说明了libevent库在编译的时候已经决定了所使用的I/O复用机制,系统中提供了五种机制:在这里指选择一种来说明 epoll

在even-internal.h文件中有一个结构体,

38 struct eventop { 39     const char *name; 40     void *(*init)(struct event_base *); 41     int (*add)(void *, struct event *); 42     int (*del)(void *, struct event *); 43     int (*dispatch)(struct event_base *, void *, struct timeval *); 44     void (*dealloc)(struct event_base *, void *); 45     /* set if we need to reinitialize the event base */ 46     int need_reinit; 47 };

这个结构体中的每个字段,都是函数指针,函数指针其实就是C语言中的多态,上面的这五个字段在编译的时候指向某个系统调用中的五个函数。也就是event_base中的evsel指针。在epoll机制中,首先封装了struct event :

59 struct evepoll { 60     struct event *evread; 61     struct event *evwrite; 62 };

接下来又是一个结构体:

64 struct epollop { 65     struct evepoll *fds; 66     int nfds; 67     struct epoll_event *events; 68     int nevents; 69     int epfd; 70 };
然后是五个函数,就是event中需要的五个函数
72 static void *epoll_init (struct event_base *); 73 static int epoll_add    (void *, struct event *); 74 static int epoll_del    (void *, struct event *); 75 static int epoll_dispatch   (struct event_base *, void *, struct timeval *); 76 static void epoll_dealloc   (struct event_base *, void *);
然后初始化一个结构体, 这个结构体的名字就是epollops

78 const struct eventop epollops = { 79     "epoll", 80     epoll_init, 81     epoll_add, 82     epoll_del, 83     epoll_dispatch, 84     epoll_dealloc, 85     1 /* need reinit */ 86 };
看在具体的代码中怎么使用上述的内容的:

107 static void *108 epoll_init(struct event_base *base)109 {110     int epfd, nfiles = NEVENT;111     struct rlimit rl;112     struct epollop *epollop;113 114     /* Disable epollueue when this environment variable is set */115     if (getenv("EVENT_NOEPOLL"))116         return (NULL);117 118     if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&119         rl.rlim_cur != RLIM_INFINITY) {120         /*121          * Solaris is somewhat retarded - it's important to drop122          * backwards compatibility when making changes.  So, don't123          * dare to put rl.rlim_cur here.124          */125         nfiles = rl.rlim_cur - 1;126     }127 128     /* Initalize the kernel queue */129 130     if ((epfd = epoll_create(nfiles)) == -1) {131         if (errno != ENOSYS)132             event_warn("epoll_create");133         return (NULL);134     }135 136     FD_CLOSEONEXEC(epfd);137 138     if (!(epollop = calloc(1, sizeof(struct epollop))))139         return (NULL);140 141     epollop->epfd = epfd;142 143     /* Initalize fields */144     epollop->events = malloc(nfiles * sizeof(struct epoll_event));145     if (epollop->events == NULL) {146         free(epollop);147         return (NULL);148     }149     epollop->nevents = nfiles;150 151     epollop->fds = calloc(nfiles, sizeof(struct evepoll));152     if (epollop->fds == NULL) {153         free(epollop->events);154         free(epollop);155         return (NULL);156     }157     epollop->nfds = nfiles;158 159     evsignal_init(base);160 161     return (epollop);162 } 在这篇文章中使用了init,其实如果系统在编译中使用的epol机制,最终调用的就是上面的这个函数。

在130行调用了系统调用event_create,生成的32000个套接字描述符,从143行开始初始化,也就是32000个描述符,每个描述符都是一个struct epoll_event,在这个函数体中最终生成的一些列东西都是返回一个struct epollop,也就是上面其中一个结构体的封装。函数最后的返回值也是epollop.下面来看看这个函数式怎么初始化struct epollops的。在130行event_create返回值的epfd最终赋值给了epollop->epfd,而epollop->fds在151行是动态申请可空间,大小也是nfiles=NEVENT = 32000,epollop中的nevents和nfds都是NEVENT.这里暂时不讨论关于信号的任何内容。

这个函数也就是相当于初始化了一个struct epollop.



1 0
原创粉丝点击