您的位置:首页 > 其它

I/O多路复用---select、poll、epoll

2016-04-29 19:30 225 查看
select,poll,epoll都是I/O多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

select:系统提供select函数来实现多路复用输入/输出模型。select系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变。

函数原型:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct
timeval *timeout)

函数参数:参数nfds是需要监视的最大的文件描述符值+1

rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合。

struct timeval结构用于描述一段时间长度,如果在这个时间内需要监视的描述符没有事件发生则函数返回,返回值为0。

下面的宏提供了处理这三种描述词组的方式:

FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位

FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真

FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位

FD_ZERO(fd_set *set);用来清除描述词组set的全部位

函数返回值:执行成功则返回文件描述符状态已改变的个数

返回0表示描述符状态改变前已超过timeout时间,没有返回。

错误返回-1

select缺点:(1)每次调用select,都要把fd集从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)每次调用select,都要在内核态遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持一个进程打开的描述符数量有限,由FD_SETSIZE设置,默认2048

poll:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备状态就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪状态,则挂起当前进程,直到设备就绪或者主动超时。不同于select使用三个位图表示三个fdset的方式,poll使用一个pollfd的指针实现,也没有最大连接数的限制。

poll没有最大连接数的限制,原因在于poll是基于链式存储的

poll缺点:(1)poll虽然没有最大数量限制,但是数量过大后性能也会下降。和select一样,poll返回后需要轮询pollfd来获取就绪的描述符。

(2)poll还有一个特点是 水平触发,如果报告了fd后,没有被处理,那么下次poll会再次报告该fd

epoll:select和poll的改进。相对于select和poll来说,epoll更灵活,没有描述符限制。

epoll的相关系统调用:epoll_create,epoll_ctl,epoll_wait

int epoll_create(int size)创建一个epoll句柄,当创建好epoll句柄后,它就会占用一个fd值,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event) epoll的事件注册函数,第一个参数是epoll_create()的返回值,第二个参数表示动作,第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事。

int epol_wait(int epfd,struct epoll_event *events,int maxevents,int timeout)收集在epoll监控的事件中已经发送的事件

epoll优点:(1)支持一个进程打开大数目的socket描述符

(2)IO效率不随fd数目增加而线性下降,不是轮询方式。只有活跃的socket才会主动调用callback函数,其他idle状态则不会。在一些benchmark中,如果所有的socket基本都是活跃的,epoll并不比select和poll有什么效率。相反,如果过多使epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率远在select和poll之上了。

(3)使用mmap加速内核与用户空间的消息传递,即epoll使用mmap减少复制开销

(4)内核微调

epoll工作模式:ET (edge-triggered)是高速工作方式,只支持no-block socket,它效率要比LT更高。ET与LT的区别在于,当一个新的事件到来时,ET模式下当然可以从epoll_wait调用中获取到这个事件,可是如果这次没有把这个事件对应的套接字缓冲区处理完,在这个套接字中没有新的事件再次到来时,在ET模式下是无法再次从epoll_wait调用中获取这个事件的。而LT模式正好相反,只要一个事件对应的套接字缓冲区还有数据,就总能从epoll_wait中获取这个事件。因此,LT模式下开发基于epoll的应用要简单些,不太容易出错。而在ET模式下事件发生时,如果没有彻底地将缓冲区数据处理完,则会导致缓冲区中的用户请求得不到响应。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: