转载:http://blog.csdn.net/mr253727942/article/details/50827127

一、IO多路复用定义

IO多路复用允许应用在多个文件描述符上阻塞,并在某一个可以读写时通知, 一般遵循下面的设计原则:、

  1. IO多路复用:任何文件描述符准备好IO时进行通知
  2. 在文件描述符就绪前进行睡眠。
  3. 唤醒:哪个准备好了
  4. 在不阻塞的情况下处理所有IO就绪的文件描述符
  5. 返回第一步

Linux下提供了三种IO多路复用方案,select、poll和epoll。

二、select IO 多路复用

看一下select 函数的定义:

int select (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);FD_CLR(int fd, fd_set *set);FD_ISSET(int fd, fd_set *set);FD_SET(int fd, fd_set *set);FD_ZERO(fd_set *set);

上面的定义中可以看到select主要检测三类文件描述符,分别等待不同的事件。

  • readfds

    确认是否有可读数据
    
  • writefds

    确认是否有可写数据
    
  • exceptefds

    确认是否有异常发生或者出现带外数据。
    

第一个参数n,等于所有集合中文件描述符的最大值加一。select()的调用者需要找到最大的文件描述符值加一作为第一个参数。

成功返回时,返回哪一个文件描述符,就说明该文件描述符准备好无阻塞IO。对于timeout,select操作可以设置一个超时时间,超时后即使没有文件描述符IO就绪也会返回。

select的缺点:

1.每次调用select,都需要把fd集合从用户态拷贝到内核态 
2。同时需要遍历所有fd 
3。支持的文件描述符默认只有1024

三、poll IO 多路复用

poll()系统调用也是一个IO多路复用解决方案,解决了 一些select的不足,下面给出poll的定义:

#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds,
int timeout);

与上面的select()使用三个文件描述符集合不同,poll()使用了一个简单的nfds个pollfd结构体构成的数组,fds指向该数组,结构体定义如下:

#include <sys/poll.h>
struct pollfd {int fd; /* file descriptor */short events; /* requested events to watch */short revents; /* returned events witnessed */
};

每个pollfd指定了唯一一个文件描述符,每个结构体中的events字段是要坚实的文件描述符事件的一组位掩码。revents字段是发生在该文件描述符上的事件的位掩码,内核在返回时设置这个字段,所有events字段请求的时间都可能在revents字段中返回。下面是合法的事件:

POLLIN       没有数据可读
POLLRDNORM   有正常数据可读。
POLLRDBAND   有优先数据可读。
POLLPRI      有高优先级数据可读。
POLLOUT      写操作不会阻塞。
POLLWRNORM   写正常数据不会阻塞。
POLLBAND     写优先数据不会阻塞。
POLLMSG      有一个sigpoll消息可用。

除此之外还可能返回几个异常信息:

POLLER       文件描述符有错误。
POLLHUP      文件描述符上有挂起事件。
POLLNVAL     给出的文件描述符非法。

监视一个文件描述符是否可以读写,可以设置events为POLLIN | POLLOUT,返回时将在revents中检查是否有相应标志。如果设置了POLLIN,或者POLLOUT则代表可以操作相关事件。

timeout参数指定在任何IO就绪前需要等待时间的长度,负值表示永远等待,一个零值表示调用立即返回,列出所有为准备好的IO,不等待任何时间。

四、poll()与select()的区别

poll()系统调用优于select():

  • poll()不需要使用者计算最大的文件描述符值加一和传递该参数。
  • poll()在应对较大值的文件描述符时效率更好,如果用select()监视值为900的文件描述符–内核需要检查每个集合中的每个bit位,知道第九百个。
  • select()的文件描述符集合是静态大小,但是poll()可以创建合适大小的数组,只需要传递结构体数组即可。
  • select()文件描述符集合会在返回时重新创建,每个调用都必须要重新初始化它们。poll()系统调用分离了events字段和revents字段,无需改变就能重用。
  • 相对于poll(),select()移植性更好
  • select()提供了更好的超时方案。

五、epoll IO 多路复用

上面的两种方式中,每次调用都需要所有被监听的文件描述符,内核必须遍历所有的文件描述符,当文件描述符变得很大,这里的遍历就会成为瓶颈。

epoll将监听注册从实际监听中分离出来,完成了真正的事件等待。

1、先创建一个新的epoll实例:

#include <sys/epoll.h>
int efpd =  epoll_create (int size)

size是告诉内核大概需要监听的文件描述符数目。

2、控制epoll

epoll_ctl()可以向指定的epoll上下文中加入或删除文件描述符。

#include <sys/epoll.h>
int epoll_ctl (int epfd, int op, int fd, struct
epoll_event *event);

头文件

六、IO实现的内核内幕

主要涉及三个内核子系统:

  1. 虚拟文件系统(VFS)
  2. 页缓存
  3. 页回写

虚拟文件系统

虚拟文件系统是linux内核的文件操作的抽象机制,允许内核在无需了解文件系统类型的情况下,使用文件系统函数和操作文件系统数据。

VFS实现这种抽象的方法是使用一种通用文件模型,它是所有linux文件系统的基础,通用文件模型提供了linux内核文件系统必须遵循的框架,框架提供了了hooks支持读写、建立链接、同步等其他功能。

当然这种方法规定了一些共性,比如必须要有inode,super block(超级块)和目录条目等。

页缓存

页缓存是一种在内存中保存最近在磁盘文件系统上访问过的数据的方式。页缓存是内核寻找文件系统数据的第一目的地。只有缓存找不到时内核才会调用存储子系统从磁盘读数据。

linux中页缓存大小是动态的,随着IO操作将越来越多的数据带入内存,页缓存会随之增大,消耗更多的内存,如果页缓存确实消耗掉了所有空闲内存,页缓存会释放最少使用页。

页回写

内核使用缓冲区来延迟写操作,当一个进程发起写请求,数据被拷贝到缓冲区,这时将缓冲区标记为“脏”数据,如果对同一个数据块有新的写请求,缓冲区就更新为新数据,把“脏”缓冲区写入磁盘。有两个条件会触发这种回写:

  1. 当空闲内存小于设定的阀值,会将缓冲区回写。
  2. 当一个脏的缓冲区寿命超过阀值也会回写防止数据不确定。

回写由一些pdflush内核线程操作,当上述两种情况发生,线程被唤醒开始刷新脏缓冲区。

Linux :IO多路复用模型相关推荐

  1. NIO详解(三):IO多路复用模型之select、poll、epoll

    1. 前言 最近在研究基于Java的高性能异步非阻塞I/O框架Netty,因为最近做的RDMAChannel要用到其中的思想.Netty底层是通过大量的NIO实现的,通过分析底层NIO源码,发现NIO ...

  2. 引入了一个IO多路复用模型

    我们前面讲的非阻塞仍然需要进程不断的轮询重试.能不能实现当数据可读了以后给程序一个通知呢?所以这里引入了一个IO多路复用模型,I/O多路复用的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可 ...

  3. Linux IO多路复用之Select简史

    内容目录 前言早期的UnixTCP/IP诞生后终端复用套接字章节回顾结论引用 前言 最近我一直在思考 Linux 中的多路复用,即 epoll(7)[1]系统调用.我很好奇 epoll与Windows ...

  4. linux IO多路复用 select epoll

    概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程 通俗理解(摘自网上一大神) 这些名词比较绕口,理解涵义就好.一个epoll场景:一个酒吧服务员(一个线程),前 ...

  5. linux io多路复用详解,Linux系统中IO多路复用

    文章目录 1 什么是IO多路复用 1.1 阻塞IO模型 1.2 非阻塞IO模型 1.3 IO复用模型 1.4 信号驱动IO模型 1.5 异步IO模型 2 IO多路复用,epoll 1 什么是IO多路复 ...

  6. Linux IO 多路复用是什么意思?

    写在前面:本文整理于知乎,原文链接为http://www.zhihu.com/question/32163005/answer/55772739,作者:罗志宇 再次向作者表示感谢~~ 假设你是一个机场 ...

  7. linux下多路复用模型之Select模型

    Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...

  8. Linux IO多路复用之epoll网络编程(含源码)

    前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...

  9. Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)

    本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一行,然 ...

最新文章

  1. 斯诺登称美向日提供监控系统 日本人或遭大规模监控
  2. 美国远程医疗公司First Stop Health获210万天使投资
  3. boost::hana::count_if用法的测试程序
  4. Redis的诞生历程
  5. [vue] 如果让你教一个2-3年经验前端经验的同事使用vue,你该怎么教?
  6. java url重写 session_Java Web学习之Cookie和Session的深入理解
  7. 【Flink】报错Could not forward element to next operator Buffer pool is destroyed
  8. 【AD18新手入门】从零开始制造自己的PCB
  9. 电工模拟接线软件 app_超全的电工接线方法口诀
  10. javaeye改名之后
  11. matlab covar,delta CoVaR 系统性风险指标计算
  12. VBS以强制启用宏的方式打开EXCEL文件,无视用户设置
  13. 必做作业三_ShareX结构化原型设计
  14. 【Jekyll】使用GitHub Pages + Jekyll搭建自己的技术博客,Jekyll服务器的搭建
  15. c# wifi串口通信_C#中的串口通信
  16. 计算机教研组工作计划表,2017学年第一学期信息技术教研组工作计划
  17. 如何用Python判断某年某月有多少天
  18. HTML期末大作业: 学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计代做
  19. oracle匹配excel数据,如何用Excel直接查询Oracle中的数据
  20. 潜艇的主动声呐探测信号

热门文章

  1. class-感知机Perception
  2. maven 配置 pom.xml 打包生成:单jar包/jar包+lib目录
  3. 基于JAX-WS的webService开发实例
  4. 百度云推送的简单集成
  5. 小试---EF5.0入门实例1
  6. 一个简单的python日志服务器
  7. [我研究]Behavior Based Software Theft Detection - Hawk
  8. python三维数据图_matplotlib中三维数据的热图
  9. html click事件 参数,vue 实现click同时传入事件对象和自定义参数
  10. logstash 吞吐量优化_1002-谈谈ELK日志分析平台的性能优化理念