EPOLL使用心得

原创 2015年07月07日 22:44:43

关于epoll是干什么的,网上已经有很多了,不再赘述,我就是想写写我是怎么用的,很初级的用法。
epoll的用法非常简单,简单到三个函数已经足够了。他们分别是

epoll描述符的创建

int epoll_create(int size) 

该函数生成一个epoll专用的文件描述符(FD)。本质就是在内核申请一定的空间,用来存放你想关注的socket fd上是否发生了什么事件(读写)。size就是你在这个epoll fd上能关注的最大的socket fd数目。只要你有空间,随便你开到多大。

epoll描述符的修改

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

该函数用于控制某个epoll fd上的事件,可以注册,修改,删除事件。
参数:
1. epfd 这个没什么好说,就是你想作用的epoll fd
2. op 对epoll fd要进行的操作。可取的有EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL
3. fd 关联的文件描述符,一般是某个socket fd
4. event 指向epoll_event的指针
如果调用成功返回0,失败则返回-1

epoll_ctl中用到的数据结构

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 */   
};  

在epoll_data中,我们可以自定义需要的东西,所用到的就是void *ptr,他可以指向一个自定义的数据结构,在那个数据结构中,我们可以定义callback函数,或者一些类似状态的东西,供epoll fd被唤醒时用。
epoll_event 中的events有如下几种事件类型:
1. EPOLLIN:可读
2. EPOLLOUT:可写
3. EPOLLPRI:有紧急的数据可读
4. EPOLLERR:发生错误
5. EPOLLHUP:被挂断
6. EPOLLET:有事件发生
在设置要处理的事件类型时,我们一般这么写:ev.events=EPOLLIN|EPOLLOUT;

epoll轮询

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

用于轮询epfd上I/O事件的发生
参数:
1. epfd:由epoll_create生成的epoll fd
2. epoll_event:用于回传待处理事件的数组
3. maxevents:每次能处理的最多的事件数
4. timeout:等待I/O事件发生的超时值

用法如下所示:

//build the epoll event for recall
struct epoll_event ev[20];
int nfds = epoll_wait(epoll_fd,ev,20,1000);
for(int i=0; i<nfds; ++i){
    if(ev[i].data.fd==sock)
    ...
}

epoll_wait运行的原理是
等侍注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中。

需要注意的是:

epoll_wait会将注册在epfd上的socket fd的事件类型给清空,所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设置socket fd的事件类型。这时不用EPOLL_CTL_ADD,因为socket fd并未清空,只是事件类型清空。这一步非常重要。

epoll有两种工作方式:LT和ET,默认是LT。

LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.

ET (edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。所以在这种情况下,ET读的读要一直读,写要一直写,对程序员提出了更高的要求。

如果程序中用了两个线程,一个监听accept,用一个监听epoll_wait,这个时候listen socket fd用默认的阻塞就好了。如果只有一个线程,那么listen socket
fd在创建的时候就要对他进行非阻塞的声明。

fcntl(listenFd, F_SETFL, O_NONBLOCK);

epoll详解和使用

什么是epoll epoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll。当然,这不是2.6内核才有的,它是在2.5.44内核中被引进的(epoll(4) is a new ...
  • petershina
  • petershina
  • 2016年01月31日 15:42
  • 1379

彻底学会使用epoll(三)——ET的读操作实例分析

首先看程序一,这个程序想要实现的功能是当用户从控制台有任何输入操作时,输出”hello world!”。 l 程序一    点击(此处)折叠或打开 #i...
  • weiyuefei
  • weiyuefei
  • 2016年08月18日 17:11
  • 1391

epoll用法详解 优点

在linux的网络编程中,很长的时间都在使用select来做事件触发。在linux新的内核中,有了一种替换它的机制,就是epoll。相比于select,epoll最大的好处在于它不会随着监听fd数目的...
  • kongxian2007
  • kongxian2007
  • 2016年08月15日 17:31
  • 600

高级I/O复用技术:Epoll的使用及一个完整的C实例

高性能的网络服务器需要同时并发处理大量的客户端,而采用以前的那种对每个连接使用一个分开的线程或进程方法效率不高,因为处理大量客户端的时候,资源的使用及进程上下文的切换将会影响服务器的性能。一个可替代的...
  • woshinia
  • woshinia
  • 2014年04月03日 12:21
  • 6147

windows完成epoll移植

windows完成epoll移植   2012-03-09 09:16:03|  分类: 默认分类|举报|字号 订阅      ...
  • boshuzhang
  • boshuzhang
  • 2016年04月14日 09:30
  • 2012

处理大并发之一 对epoll的理解,epoll客户端服务端代码

处理大并发之二 对epoll的理解,epoll客户端服务端代码 序言: 该博客是一系列的博客,首先从最基础的epoll说起,然后研究libevent源码及使用方法,最后研究nginx和node.js,...
  • zhuxiaoping54532
  • zhuxiaoping54532
  • 2017年02月22日 18:13
  • 615

Linux下的socket编程实践(九) epoll实现高并发的原理及其使用

在 linux 没有实现 epoll 事件驱动机制之前,我们一般选择用 selec t或者 poll 等IO多路复用的方法来实现并发服务程序(详见此链接)。在大数据、高并发、集群等一些名词唱得火热...
  • NK_test
  • NK_test
  • 2015年10月22日 12:03
  • 4125

通过完整示例来理解如何使用 epoll

网络服务器通常使用一个独立的进程或线程来实现每个连接。由于高性能应用程序需要同时处理大量的客户端,这种方法就不太好用了,因为资源占用和上下文切换时间等因素影响了同时处理大量客户端的能力。另一种方法是在...
  • andylauren
  • andylauren
  • 2016年09月25日 11:48
  • 654

select和epoll的性能差别

select和epoll的性能差别select原理概述调用select时,会发生以下事情: 1. 从用户空间拷贝fd_set到内核空间; 2. 注册回调函数__pollwait; 3. 遍历所有fd,...
  • qq_16836151
  • qq_16836151
  • 2016年08月01日 21:40
  • 622

socket编程 -- epoll模型服务端/客户端通信的实现

本例实现如下功能: 支持多客户端与一个服务端进行通信,客户端给服务端发送字符串数据,服务端将字符串中小写转为大写后发送回客户端,客户端打印输出经转换后的字符串。 例如:发送abcde,打印输出AB...
  • y396397735
  • y396397735
  • 2016年02月17日 14:43
  • 2387
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:EPOLL使用心得
举报原因:
原因补充:

(最多只允许输入30个字)