最近看了《后台开发核心技术与应用实践》有关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. 一篇RxJava友好的文章(二)

    上一篇文章介绍了rxjava的基本用法,和一些常用的操作符,以及rxjava的链式操作带来的好处.由于rxjava非常的强大,让我如此的痴迷,我打算写五篇文章,专门讲解rxjava 常见的操作符和用法 ...

  2. Oracle 启动 停止JOB

    转自:https://www.cnblogs.com/qianbing/p/6971633.html --查看job下次执行时间以及间隔时间 '; --启动job ); --停用job EXEC DB ...

  3. Windows平台下源码分析工具

    最近这段时间在阅读 RTKLIB的源代码,目前是将 pntpos.c文件的部分看完了,准备写一份文档记录下这些代码的用处.处理过程.理论公式来源.注意事项,自己还没有弄明白的地方.目前的想法是把每一个 ...

  4. python基础数据类型之字典的操作

    一. 字典的简单介绍字典(dict)是python中唯一的一个映射类型.他是以{ }括起来的键值对组成. 在dict中key是唯一的. 在保存的时候, 根据key来计算出一个内存地址. 然后将key- ...

  5. mongdb安装配置

    一.先登录Mongodb官网https://www.mongodb.com/download-center#community 下载   安装包.32.64位的都行. 或者查看我的百度云(使用win7 ...

  6. 传输控制协议(TCP)

    传输控制协议(TCP)[来自Unix网络编程(卷一)第2章] 1.TCP是一个面向连接.可靠性的传输协议: 2.TCP含有用于动态估算客户与服务器之间往返时间(RTT)的算法,以便它知道等待一个确认需 ...

  7. Linux编译移植Qt5的环境_Xillinx的ZYNQ平台

    Linux编译Qt环境 2017年的十一假期,足不出户,一个人在教研室里面搞Qt的移植.我手里面有Samsung的CortexA8,Samsung的 CortexA53还有Ti的Sitara系列的AM ...

  8. git 代码托管使用方法

    Git代码托管 1 准备材料 在coding,github这些代码托管网站上申请一个账户. Linux平台什么需要一个git,如ubuntu 需要 $ sudo apt-get install git ...

  9. [BZOJ3714]Kuglarz(最小生成树)

    Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,-,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品.花费\(C_{i,j}\)元,魔术师就会告诉 ...

  10. Hive 中的 UDF

    LanguageManual UDF 一.分类 UDF:User defined function 用户定义函数 一进一出 UDAF:User defined aggregation function ...