认识epoll

linux下的epoll(7)函数,其有着良好的就绪事件通知机制。Epoll 是被linux2.6开始引进的,可是不被其余的类UNIX系统支持,它提供了一种相似select或poll函数的机制:
a. Select(2)只可以同时管理FD_SETSIZE(默认为1024)数目的文件描述符,而且必须遍历全部的描述符来检查就绪的描述符。
b. poll(2)没有固定的描述符上限这一限制,可是每次必须遍历全部的描述符来检查就绪的描述符,这个过程的时间复杂度为O(n)。
epoll没有select这样对文件描述符上限的限制,也不会像select/poll那样进行线性的遍历。所以epoll处理大并发链接有着更高的性能。html

咱们从select那里仅仅知道了,有I/O事件发生了,但却并不知道是那几个流(可能有一个,多个,甚至所有),咱们只能无差异轮询全部流,找出能读出数据,或者写入数据的流,对他们进行操做。
可是使用select,咱们有O(n)的无差异轮询复杂度,同时处理的流越多,每一次无差异轮询时间就越长。
epoll能够理解为event poll,不一样于忙轮询和无差异轮询,epoll只会把哪一个流发生了怎样的I/O事件通知咱们(时间复杂度下降到了O(1))。此时咱们对这些流的操做都是有意义的。linux


Epoll相关操做函数介绍:
1. epoll_create(2) or epoll_create1(2)(有着不一样的参数值)用来建立epoll实例。
/usr/include/sys/epoll.h
extern int epoll_create (int __size) ;
RETURN:>0, 成功;-1, 出错
函数描述:
(1) epoll_create返回的是一个文件描述符,也就是说epoll是以特殊文件的方式体现给用户
(2) __size提示操做系统,用户可能要使用多少个文件描述符,该参数已经废弃,填写一个大于0的正整数
程序员

2. epoll_ctl(2)用来增长或移除被epoll所监听的文件描述符。数组

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

RETURN:0,成功;-1,出错并发

函数描述:
(1) epfd为epoll_create建立的epoll描述符
(2) epoll_ctl函数对epoll进行op类型的操做,op选项为
EPOLL_CTL_ADD,对fd描述符注册event事件
EPOLL_CTL_MOD,对fd描述符的event事件进行修改
EPOLL_CTL_DEL,删除已注册的event事件socket

3. epoll_wait(2)用来等待发生在监听描述符上的事件。它会一直阻塞直到事件发生。
#include函数

int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);

RETURN:>0,发生事件个数;=0,时间到;-1,出错性能

函数描述:
epoll_wait与select函数相似,同步地等待事件发生
(1) epfd,标识epoll的文件描述符
(2) events,指向传入操做系统的一个epoll_event数组
(3) maxevents,表示传入数组的大小,必须大于0
当有事件发生,Linux会填写events结构,返回给应用程序。因为epoll_wait同步等待,有可能被信号中断,返回EINTR错误.
这里有一个比较重要的问题:从epoll_wait返回的events中,该如何知道是哪一个描述符上的事件:在注册epoll事件的时候,必定要填写epoll_data,不然咱们将分不清触发的是哪一个描述符上的事件。
Epoll的两种模式:
1. 水平触发(LT):使用此种模式,当数据可读的时候,epoll_wait()将会一直返回就绪事件。若是你没有处理彻底部数据,而且再次在该 epoll实例上调用epoll_wait()才监听描述符的时候,它将会再次返回就绪事件,由于有数据可读。LT(level triggered)是缺省的工做方式,而且同时支持block和no-block socket.。
2. 边缘触发(ET):使用此种模式,只能获取一次就绪通知,若是没有处理彻底部数据,而且再次调用epoll_wait()的时候,它将会阻塞,由于就绪事件已经释放出来了。ET只支持非阻塞socket。
ET的效能更高,可是对程序员的要求也更高。在ET模式下,咱们必须一次干净而完全地处理完全部事件。
传递给epoll_ctl(2)的Epoll事件结构体以下所示:ui

typedef union epoll_data
{
void*ptr;
intfd;
__uint32_t u32;
__uint64_t u64;
}epoll_data_t;

struct epoll_event
{
__uint32_t events;/* Epoll events */
epoll_data_t data;/* User data variable */
};

对于每个监听的描述符,可以关联一个整形数据或指向用户数据的指针。spa

epoll的事件类型:
– EPOLLIN,读事件
– EPOLLOUT,写事件
– EPOLLPRI,带外数据,与select的异常事件集合对应
– EPOLLRDHUP,2.6.17 版本内核中增长了 EPOLLRDHUP 事件,表明对端断开链接(参见EPOLL事件之EPOLLRDHUP)
– EPOLLERR,错误事件
– EPOLLET,设置事件为边沿触发
– EPOLLONESHOT,只触发一次,事件自动被删除
一个文件描述符在一个epoll实例上只能注册一次,一个描述符在同一个epoll实例上注册屡次,会产生EEXIST的错误。
一样,删除epoll的事件,只需描述符就够了
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);

引用:

epoll实例

epoll 或者 kqueue 的原理是什么?

相关文章
相关标签/搜索