Linux中的epoll

1.epoll函数原型

epoll操作由三个函数组成:

#include <sys/epoll.h>
int epoll_create(int size);
            //成功时返回epoll文件描述符,失败时返回-1
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
            //成功时返回0,失败时返回-1
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
            //成功时返回发生事件的文件描述数,失败时返回-1

(1)epoll_create:创建保存epoll文件描述符的空间。

调用epoll_create函数时创建的文件描述符保存空间称为“epoll例程”。但要注意:size参数只是应用程序向操作系统提的建议,操作系统并不一定会生成一个大小为size的epoll例程。
(2)epoll_ctl:向空间注册并注销文件描述符。
参数epfd指定注册监视对象的epoll例程的文件描述符,op指定监视对象的添加、删除或更改等操作,有以下两种常量:

1)EPOLL_CTL_ADD:将文件描述符注册到epoll例程

2)EPOLL_CTL_DEL:从epoll例程中删除文件描述符

3)EPOLL_CTL_MOD:更改注册的文件描述符的关注事件发生情况
  fd指定需要注册的监视对象文件描述符,event指定监视对象的事件类型。epoll_event结构体如下:  
struct epoll_event
{
__uint32_t events;
epoll_data_t data;
}
typedef union epoll_data
{
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
}epoll_data_t;
epoll_event的成员events中可以保存的常量及所指的事件类型有以下:

1)EPOLLIN:需要读取数据的情况

2) EPOLLOUT:输出缓冲为空,可以立即发送数据的情况

3) EPOLLPRI:收到OOBO数据的情况

4) EPOLLRDHUP:断开连接或半关闭的情况,这在边缘触发方式下非常有用

5) EPOLLERR:发生错误的情况

6) EPOLLET:以边缘触发的方式得到事件通知

7) EPOLLONESHOT:发生一次事件后,相应文件描述符不再收到事件通知。因此需要向epoll_ctl函数的第二个参数EPOLL_CTL_MOD,再次设置事件。
(3)epoll_wait:与select函数类似,等待文件描述符发生变化。

操作系统返回epoll_event类型的结构体通知监视对象的变化。timeout函数是为毫秒为单位的等待时间,传递-1时,一直等待直到事件发生。
声明足够大的epoll_event结构体数组后,传递给epoll_wait函数时,发生变化的文件符信息将被填入该数组。因此,不需要像select函数那样针对所有文件符进行循环。

2.epoll与select/poll的区别

本质上都是同步I/O

三者都是I/O复用,本质上都属于同步I/O。因为三者只是负责通知应用程序什么时候数据准备好了,实际的I/O操作还是在由应用程序处理;如果是异步I/O的话,实际I/O由内核处理,然后再通知应用程序。这一点要搞清楚。
  
2.1 epoll 相比select、poll 的缺点:

(1)Linux系统独有:epoll函数并不是Unix系统通用,所以不适合开发兼容性强的程序;

(2)select、poll都只有一个函数,而epoll有三个(epoll_create,epoll_ctl和epoll_wait),操作起来更复杂,并且由于要实现回调机制,epoll的内部实现也更加复杂。如果并发量小且连接不频繁的话,最好使用select和poll,性能可能更好。

2.2 epoll相比select、poll的优点

(1)每次调用select、poll,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大,而epoll函数只有使用epoll_ctl函数时才会进行fd的拷备,并且只拷备增加的fd;

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大,而epoll函数只传递所有新注册事件的fd;

(3)select支持的文件描述符数量太小了,默认是1024,而epoll函数所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048。

1 select的低效率
  select/poll函数效率比较低,主要有以下两个原因:

(1)调用select函数后需要对所有文件描述符进行循环查找
(2)每次调用select函数时都需要向该函数传递监视对象信息

在这两个原因中,第二个原因是主要原因:每次调用select函数时,应用程序都要将所有文件描述符传递给操作系统,这给程序带来很大的负担。在高并发的环境下,无论怎样优化应用程序的代码,都无法完成应用的服务。

所以,select与poll并不适合以Web服务器端开发为主流的现代开发环境,只在要求满足以下两个条件是适用:

(1)服务器端接入者少

(2)程序要求兼容性

2 Linux的epoll机制
  由上一节,我们需要一种类似于select的机制来完成高并发的服务器。需要有以下两个特点(epoll和select的区别):

(1)应用程序仅向操作系统传递1次监视对象
(2)监视范围或内容发生变化是,操作系统只通知发生变化的事项给应用程序

3.其他系统有没有epoll的替代品

Linux的支持方式是epoll,Windows的支持方式是IOCP
mac下采用kqueue机制代替epoll实现io复用,二者很相似。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值