未完成。。。。。
主要三大接口,epoll_create,epoll_ctl和epoll_wait。
原型
extern int epoll_create (int __size) __THROW;
实例化epoll,返回epfd,epoll的fd。参数就是个size,你想让epoll保证能处理多少连接(只是保证),影响不大吧,新内核都不要传参了,参数空着用就行。
还有一个参数是flags的epoll_create1,我跟他不熟。
PS:_THROW宏——是说可能有异常抛出——这样定义的原因是兼容C和C++,C什么都不做,C++用throw()
</usr/include/argp.h> #ifndef __THROW #define __THROW #endif #ifndef __THROW #ifndef __GNUC_PREREQ #define __GNUC_PREREQ(maj,min) (0) #endif #if defined __cplusplus && __GNUC_PREREQ(2,8) #define __THROW throw() #else #define __THROW #endif #endif
原型
extern int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) __THROW;
原型
extern int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout);
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ };
提供了EPOLLIN、EPOLLONESHOT等枚举选项,可以或操作,取并集,这些枚举是互相独立不干扰的,其实就是位操作。
enum EPOLL_EVENTS { EPOLLIN = 0x001, #define EPOLLIN EPOLLIN EPOLLPRI = 0x002, #define EPOLLPRI EPOLLPRI EPOLLOUT = 0x004, #define EPOLLOUT EPOLLOUT EPOLLRDNORM = 0x040, #define EPOLLRDNORM EPOLLRDNORM EPOLLRDBAND = 0x080, #define EPOLLRDBAND EPOLLRDBAND EPOLLWRNORM = 0x100, #define EPOLLWRNORM EPOLLWRNORM EPOLLWRBAND = 0x200, #define EPOLLWRBAND EPOLLWRBAND EPOLLMSG = 0x400, #define EPOLLMSG EPOLLMSG EPOLLERR = 0x008, #define EPOLLERR EPOLLERR EPOLLHUP = 0x010, #define EPOLLHUP EPOLLHUP EPOLLRDHUP = 0x2000, #define EPOLLRDHUP EPOLLRDHUP EPOLLONESHOT = (1 << 30), #define EPOLLONESHOT EPOLLONESHOT EPOLLET = (1 << 31) #define EPOLLET EPOLLET };
仔细算就知道了,反正就是一个32位标志,每个设置都占用不同位,没有冲突,甚至从这看还剩余了很多。
data是epoll_data_t类型,epoll_data_t就是结构体前边定义的那个联合体。
联合体的结构初看会比较怪异,有个void*指针,有个int fd,剩下uint32_t和uint64_t,fd肯定就是fd了,就是暂不知道打算什么时候用,指针就是核心了,这是给你用的。
uint32_t和uint64_t是干什么的?
好像是没用的!他们只是对齐用的。就因为那个void *指针。
指针是寻址用的,指针长短取决于硬件,或者说系统,64位和32位系统指针长度不一样,这个联合体epoll_data长短就会有不同,相应的,结构体epoll_event长短就会不同,这就比较麻烦了。所以联合体(是联合体,按最长的算)多加了一个u32和一个u64。
这样长度就统一了,移植会比较方便。
沿用了通信的术语,edge trigger和level trigger,关于状态,前者是来时候只通知一次,后者是一直可知。
这有时候会犯点小错误,因为有个例子工程里有了epoll.h,封装了一些epoll初始化实例化操作,他又没在epoll.h引用sys/epoll.h,而是在epoll.c中引用坏习惯。
(PS:实例化epoll_event,sizeof,他提示你sizeof不能用于不完全的类型,这其实就是没有引用头文件,该数据结构无定义)。
在某文件想使用epoll时用成了
#include "epoll.h"
其实正经的epoll头文件,至少我目前用到的linux,都是
#include <sys/epoll.h>
当然写成双引号也无妨,但是必须是sys。也可以引用epoll.h再让epoll.h去引用sys/epoll.h,这都无所谓
相应的,我用
_EPOLL_H
判定也没问题了,因为系统的是
_SYS_EPOLL_H