epoll机制

用户接口

一 epoll工作原理

别人是这样总结的。你如果想进行IO操作时,先向epoll查询是否可读或可写,如果处于可读或可写状态后,epoll会通过epoll_wait函数通知你,此时你再进行进一步的recv或send操作。
epoll仅仅是一个异步事件的通知机制,其本身并不作任何的IO读写操作,它只负责告诉你是不是可以读或可以写了,而具体的读写操作,还要应用层自己来作。epoll仅提供这种机制也是非常好的,它保持了事件通知与IO操作之间彼此的独立性,使得epoll的使用更加灵活。
epoll用到的数据结构和函数声明位置为include/sys/epoll.h,函数位于epoll_sub.c文件中。

二 主要数据结构

1 epoll_data
typedef union epoll_data 
{
    void *ptr;
    int fd;
    unsigned int u32;
    unsigned long long u64;
} epoll_data_t;
epoll_data联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到与这个client对应的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行,通过指针ptr携带应用层数据, 当事件的通知到来时,它不仅告诉你发生了什么样的事件,还同时告诉这次事件所操作的数据是哪些。奇怪的是还有u32和u64,个人觉得是为了32bit和64bit系统的对齐。
2 epoll_event
struct epoll_event 
{
    unsigned int events;
    epoll_data_t data;
};
events字段是表示感兴趣的事件和被触发的事件可能的取值是下面的一堆宏。
3 一堆宏
events字段可能的取值:
#define EPOLLIN          0x00000001//表示对应的文件描述符可以读
#define EPOLLPRI         0x00000002//表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来)
#define EPOLLOUT         0x00000004//表示对应的文件描述符可以写
#define EPOLLERR         0x00000008//表示对应的文件描述符发生错误
#define EPOLLHUP         0x00000010//表示对应的文件描述符被挂断
#define EPOLLRDNORM      0x00000040//
#define EPOLLRDBAND      0x00000080//
#define EPOLLWRNORM      0x00000100//
#define EPOLLWRBAND      0x00000200//
#define EPOLLMSG         0x00000400//
#define EPOLLET          0x80000000//表示对应的文件描述符有事件发生
//epoll_ctl()的操作:
#define EPOLL_CTL_ADD    1
#define EPOLL_CTL_DEL    2
#define EPOLL_CTL_MOD    3

三 主要函数

1 int epoll_create(int size);
生成一个epoll专用的文件描述符,它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件;其中的参数size是指定生成描述符的最大范围,就是你在这个epoll fd上能关注的最大socket fd数。
2 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。epfd:由 epoll_create 生成的epoll专用的文件描述符;op:要进行的操作,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修改、EPOLL_CTL_DEL 删除;fd:关联的文件描述符;event:指向epoll_event的指针;如果调用成功返回0,失败返回-1。
3 int epoll_wait(int epfd, struct epoll_event *events, int max, int timeout);
用于轮询I/O事件的发生;epfd:由epoll_create 生成的epoll专用的文件描述符;epoll_event:用于回传代处理事件的数组;max:每次能处理的事件数;timeout:等待I/O事件发生的超时值,-1阻塞,0非阻塞;成功返回发生事件数,失败-1。
epoll_wait运行的原理:等侍注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中。并且将注册在epfd上的socket fd的事件类型给清空,所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设置socket fd的事件类型。这时不用EPOLL_CTL_ADD,因为socket fd并未清空,只是事件类型清空。这一步非常重要。单个epoll并不能解决所有问题,特别是你的每个操作都比较费时的时候,因为epoll是串行处理的。所以你还是有必要建立线程池来发挥更大的效能。
如果你想知道这些函数的实现,是一点惊喜也不会有的,不出所料,一堆系统调用。
int
epoll_create(int size)
{
	return (syscall(__NR_epoll_create, size));
}

int
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{

	return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
}

int
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
{
	return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
}
int syscall(int number, ...);
都是syscall来搞定的。

内核实现机理


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值