最近看了《后台开发核心技术与应用实践》有关select、poll和epoll部分以及相关的一些博客,学习了这三个函数的使用方法和区别,写一个易理解的总结。

IO多路复用

之前程序中使用的IO函数都是同步的,无论阻塞式还是非阻塞式,在数据从内核拷贝到用户空间过程,用户线程都是被阻塞的。非阻塞IO只是当内核还没准备好数据时立即返回不等待,需要用户自己去不断检查内核数据是否准备好,依然不高效。IO多路复用提出了新的思路,将IO过程分为等待内核数据准备好和读取/写入内核两部分。一个IO函数监控多个IO可读/可写事件,任意1个IO设备准备好时返回(需要代码中轮询查看是哪个IO文件描述符,什么事件),再调用对应的read/write函数操作,减少不必要的等待时间,高效了很多。具体的实现有select、poll和epoll三种。

select

基于位图型集合,通过宏和fd_set结构体设置事件和检测事件的发生。最早被提出所以可移植性最好,该实现有以下缺点:1.每次调用都需要将fd集合从用户空间拷贝到内核空间,完成后再从内核空间拷贝回用户空间,fd很多时开销很大。2.实现过程是在内核中遍历所有fd,fd很多时开销很大。3.支持同时可监控的文件描述符数少,1024或2048。4.fd_set在select返回后会改变,所以再次调用select时需要再次设置fd_set
原型:int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
fd_set set;
FD_ZERO(&set); /* 将set清零*/
FD_SET(fd, &set); 将fd加入set
FD_CLR(fd, &set); 将fd从set中清除
FD_ISSET(fd, &set); 测试fd是否在set中,如果在则为true
maxfdp是描述符最大值加1,指定描述符的范围
timeout是NULL则无限等待,阻塞模式;timeout等于0则立即返回,非阻塞模式;timeout大于0则为超时时间,timeout内阻塞,到达超时时间不管怎样一定返回。
返回值:文件无变化返回0,有变化返回正值

poll

要比select高级一些,实现和select大致相同,内核中遍历所有文件描述符。使用链表式集合,不需要重复设置监控事件,同时监控文件描述符数远大于select。缺点也和select大致相同:1.每次调用都需要将pollfd集合从用户空间拷贝到内核空间,完成后再从内核空间拷贝回用户空间。2.实现过程是在内核中遍历所有pollfd

原型: int poll(struct pollfd* fds, unsigned int nfds, int timeout);
成功时返回revents不为0的文件描述符个数,0表示超时但没有任何事件发生,-1表示失败
struct pollfd{
     int fd; 文件描述符
     short events; 等待的事件,掩码控制多个事件
     short revents; 实际发生的事件,掩码控制多个事件
}
fds链表是要监控文件描述符的pollfd链表
nfds指定描述符个数
timeout:0表示立即返回,非阻塞;正值表示等待的毫秒数;负值表示无限等待,阻塞模式
返回值:revents不为0的pollfd数,-1表示出错
需要头文件#include <poll.h>
events和revents中的事件:
合法事件:
POLLIN 有数据可读
POLLRDNORM 有普通数据可读
POLLRDBAND 有优先数据可读
POLLPRI 有紧迫数据可读
POLLOUT 写数据不会导致阻塞
POLLWRNORM 写普通数据不会导致阻塞
POLLWRBAND 写优先数据不会导致阻塞
POLLMSGSIGPOLL 消息可用不会导致阻塞
非法事件:
POLLER 文件描述符发生错误
POLLHUP 文件描述符挂起事件
POLLNVAL 文件描述符非法

epoll

通过3个函数来实现,更加高效,当前使用也最多。在epoll_ctl中注册事件到epoll文件描述符中,把fd全部拷贝进内核,而不是在epoll_wait中重复拷贝。实现中内核通过为每个fd指定一个回调函数,当fd就绪时调用回调函数把就绪fd加入一个就绪链表,epoll_wait只需要查看这个就绪链表是否有就绪fd就可。可监控文件描述符数是系统可同时打开文件数(超过10万)
原型:
     int epoll_create(int size);  //返回epoll文件描述符,size表示要监听的数目 (这个返回的fd要记得close)
     int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); //epoll事件注册函数
          epfd是epoll_create返回的值
          op是动作:EPOLL_CTL_ADD/EPOLL_CTL_MOD/EPOLL_CTL_DEL分别表示:注册fd到epfd,修改已注册的fd,从epfd删除1个fd
          fd是要监听的fd
          event是告诉内核要监听什么事件
          struct epoll_event{
               __uint32_t events;  //epoll events
               epoll_data_t data; //user data variable
          }
          event是宏的集合:EPOLLIN可读;EPOLLOUT可写;EPOLLPRI紧急数据可读;EPOLLERR发生错误;EPOLLHUP被挂断;EPOLLET将EPOLL设置为边缘触发模式;EPOLLONESHOT只监听1次事件
     int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);  //等待事件发生,events是返回的事件链表;maxevents是events链表元素个数,timeout是等待毫秒数(0表示立即返回,非阻塞;正值表示等待的毫秒数;负值表示无限等待,阻塞模式 ),函数返回值是需要处理的事件数,通过events返回需要处理的事件。(通过events[i].data.fd和events[i].events匹配判断)
需要#include <sys/epoll.h>
 
转载请注明出处

参考:

《后台开发核心技术与应用实践》

http://www.cnblogs.com/Anker/p/3265058.html

IO多路复用的理解的更多相关文章

  1. IO多路复用的理解/演变过程

    目录 阻塞IO 非阻塞 IO select epoll 总结一下. 阻塞IO 服务端为了处理客户端的连接和请求的数据,写了如下代码. listenfd = socket(); // 打开一个网络通信端 ...

  2. IO多路复用,同步,异步,阻塞和非阻塞 区别

    一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...

  3. IO多路复用之select,poll,epoll个人理解

    在看这三个东西之前,先从宏观的角度去看一下,他们的上一个范畴(阻塞IO和非阻塞IO和IO多路复用) 阻塞IO:套接口阻塞(connect的过程是阻塞的).套接口都是阻塞的. 应用程序进程-----re ...

  4. Python:通过一个小案例深入理解IO多路复用

    通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...

  5. 一文彻底理解IO多路复用

    在讲解IO多路复用之前,我们需要预习一下文件以及文件描述符. 什么是文件 程序员使用I/O最终都逃不过文件. 因为这篇同属于高性能.高并发系列,讲到高性能.高并发就离不开Linux/Unix,因此这里 ...

  6. 深入理解计算机操作系统——12章:多进程,IO多路复用

    三种并行的应用程序: 1. 基于进程的并发编程: 2. 基于IO多路复用的并发: 3. 基于线程的并发编程: 12.1 基于进程的并发编程 进程的优劣: (1)进程间共享文件表,但不共享用户地址空间, ...

  7. IO多路复用?我所理解的IO模式

    1:IO的过程 当我们调用系统函数read时,一般会经历两个阶段: 1:等待数据准备(waiting for the data be ready) 2:将数组从内核拷贝到进程(从内核态到用户态)(co ...

  8. IO多路复用之select总结

    1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/ ...

  9. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

随机推荐

  1. Windows/Linux下查看系统CPU使用最高的线程

    参考:https://blog.csdn.net/qq_27818157/article/details/78688580 jstack -l 31372 > c:/31372.stack

  2. windows下配置kafka

    https://blog.csdn.net/evankaka/article/details/52421314

  3. 云计算之KVM虚拟化实战

    1 基础环境规划 1.1 主机环境规划 系统版本 主机名 IP地址 内存 磁盘 CentOS6.9 kvm-node1 10.0.0.200 2G 20G CentOS6.9 kvm-node2 10 ...

  4. JAVAOOP集合框架

    集合框架三大内容:对外的接口.接口的实现和对集合运算的算法 集合有三大类接口:List.Set.Map 共同点:都是集合接口,都可以用来存储很多对象 不同:Collection接口存储一组不唯一(允许 ...

  5. Python学习之set集合

    set集合以{}保存一组可迭代对象,如列表,字符串,set集合本身.集合内的元素若有重复的,将自动去除重复元素 a=set([1,2,3]) print(a) b=set('hello python' ...

  6. iOS各个版本的特点

    一.导航控制器中: iOS7: 栈顶控制器默认是320*480:控制器有64的高度看不见:

  7. 霍夫直线检测 opencv

    本次实验是检测图像中的直线,用到了HoughLines()和HoughLinesP()函数,其中HoughLinesP()称为累计概率霍夫变换,实验结果显示累计概率霍夫变换要比标准霍夫变换的效果好.具 ...

  8. 关于Android SDK无法更新的解决办法

    最新摆弄PhoneGap打包,所以需要安卓的环境,配置后,sdk更新实在是在慢了,上网找了一下,可能被强了,所有总结如下办法,最后弄好了,跟大家分享一下 具体步骤:1:打开SDK Manager.ex ...

  9. Maven项目Update Project自动恢复为JRE1.5的问题

    问题: 使用Eclipse建立Maven项目的时候,JDK默认为1.5在用户使用Config Build Path更新为最新JRE库比如1.8或者1.7的后,Maven项目显示JRE1.8 or 1. ...

  10. CodeForces 785E Anton and Permutation 分块

    题意: 有一个\(1 \sim n\)的排列\(A\),有\(q\)个询问: 交换任意两个元素的位置,求交换之后排列的逆序数 分析: 像这种不太容易用线段树,树状数组维护的可以考虑分块 每\(\sqr ...