最近看了《后台开发核心技术与应用实践》有关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. pwn的一些环境搭建

    <1>pwntools库安装 pwntools是一个CTF框架和漏洞利用开发库,用Python开发,由rapid设计,旨在让使用者简单快速的编写exploit. 本文将基于KUbuntu ...

  2. JavaScript编码加密

    网上看到的加密方法: JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,deco ...

  3. PHP时间日期操作增减(date strtotime) 加一天 加一月

    date_default_timezone_set('PRC'); //默认时区 //当前的时间增加5天 $date1 = "2014-11-11"; echo date('Y-m ...

  4. keil5的安装及问题

    win8+keil 注意,在进行破解的时候首先要打开一个工程,而且keil要用管理员的身份进行运行, 才可以破解完成 发现打开之后,出现这样的错误. 原因是因为在创建工程的时候在下图中点了是,要点否才 ...

  5. C++继承权限

    牢记两句话: 1.三种继承方式不影响子类对父类的访问权限,子类对父类的访问权限取决于父类的访问控制权. 2.三种继承方式是为了控制子类的调用方对父类的访问权限.比如private继承,对于子类的调用方 ...

  6. Codeforces Round #462 (Div. 2) C DP

    C. A Twisty Movement time limit per test 1 second memory limit per test 256 megabytes input standard ...

  7. 模块hashlib和logging

    Python的hashlib提供了常见的摘要算法MD5. 我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值: import hashlib md5=hashlib.md5() md5.upd ...

  8. 18 Django-组件拾遗

    一 Django的form组件 forms组件 二 Django的model form组件 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,先来一个简单的 ...

  9. 2 实现第一个Django网站 博客

    -1.理解上下文 render()渲染 request  url传来的reuqest x.html 制定返回的模板名称 context 上下文    数据库中 替换数据 0.大框架 1.创建模板 (1 ...

  10. getprop 与 dumpsys 命令

    Android 设备连接 PC 后,我们可以通过 adb 命令完成绝大多数工作.下面借助 getprop.dumpsys 来了解一些系统相关信息. 一.getprop 此命令的原理很简单,就是从系统的 ...