一、五种I/O模型

1、阻塞I/O

我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核空间(套接口缓冲区)拷贝到用户空间(recv函数提供的buf),然后recv返回,进行数据处理。

2、非阻塞I/O

我们可以使用 fcntl(fd, F_SETFL, flag | O_NONBLOCK); 将套接字标志变成非阻塞,调用recv,如果设备暂时没有数据可读就返回-1,同时置errno为EWOULDBLOCK(或者EAGAIN,这两个宏定义的值相同),表示本来应该阻塞在这里(would
block,虚拟语气),事实上并没有阻塞而是直接返回错误,调用者应该试着再读一次(again)。这种行为方式称为轮询(Poll),调用者只是查询一下,而不是阻塞在这里死等,这样可以同时监视多个设备:

while(1)

{

非阻塞read(设备1);

if(设备1有数据到达)

处理数据;

非阻塞read(设备2);

if(设备2有数据到达)

处理数据;

..............................

}

如果read(设备1)是阻塞的,那么只要设备1没有数据到达就会一直阻塞在设备1的read调用上,即使设备2有数据到达也不能处理,使用非阻塞I/O就可以避免设备2得不到及时处理。

非阻塞I/O有一个缺点,如果所有设备都一直没有数据到达,调用者需要反复查询做无用功,如果阻塞在那里,操作系统可以调度别的进程执行,就不会做无用功了,在实际应用中非阻塞I/O模型经常与IO multiplexing 一起使用。

3、I/O复用

用select来管理多个I/O,当没有数据时select阻塞,如果在超时时间内数据到来则select返回,再调用recv进行数据的复制,recv返回后处理数据。

4、信号驱动I/O

先注册SIGIO信号的处理函数,进程继续执行其他操作,当数据到来时会发送SIGIO信号给进程,然后可以在信号处理函数中调用recv进行数据的复制,然后recv返回进行数据处理。

5、异步I/O

aio_read
函数也会提供一个buf,系统调用进入内核,如果没有数据则立即返回,进程继续执行其他操作,所以叫异步I/O,当数据到来时内核自动复制数据,然后推送给用户空间,通过在aio_read中指定的信号通知进程,让其处理数据。异步I/O跟信号驱动I/O的不同之处在于,它不用调用recv进行数据的复制,如果将后者比做”拉pull“,则前者可以认为是”push推“,push的效率会高点,其实异步I/O跟windows下面的完成端口差不多,但aio_read的实现或多或少存在问题,用得也比较少。实践中用得比较多的如boost
库的asio 也是异步IO。

脚注:同步和异步的区别在于是不是要求处理消息者自己来完成将数据从内核缓冲区复制回进程缓冲区的过程。消息者阻塞和非阻塞应该是发生在消息的处理的时刻。阻塞其实就是等待,发出通知,等待结果完成。非阻塞属于发出通知,立即返回结果,没有等待过程。

对unix来讲:阻塞式I/O(默认),非阻塞式I/O(nonblock),I/O复用(select/poll/epoll),信号驱动IO都属于同步I/O,因为它们在数据由内核空间复制回进程缓冲区时都是阻塞的(不能干别的事)。只有异步I/O模型(AIO)是符合异步I/O操作的含义的,即在1数据准备完成、2由内核空间拷贝回缓冲区后
通知进程,在等待通知的这段时间里可以干别的事。

POSIX defines these two terms as follows:

A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
An asynchronous I/O operation does not cause the requesting process to be blocked.
Using these definitions, the first four I/O models—blocking,
nonblocking, I/O multiplexing, and signal-driven I/O—are all synchronous
because the actual I/O operation (recvfrom) blocks the process. Only
the asynchronous I/O model matches the asynchronous I/O
definition.

二、select函数简介

/* According to POSIX.1-2001 */
       #include <sys/select.h>
       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数1:读写异常集合中的文件描述符的最大值加1;

参数2:读集合,关心可读事件;

套接口缓冲区有数据可读
对等连接的写一半关闭。即接收到FIN段,读操作将返回0
如果是监听套接口,已完成连接队列不为空时。
套接口上发生了一个错误待处理,错误可以通过getsockopt指定SO_ERROR选项来获取。

参数3:写集合,关心可写事件;

套接口发送缓冲区有空间容纳数据。(连接一旦建立就可写)

对等连接的读一半关闭。即收到RST段之后,再次调用write操作。

套接口上发生了一个错误待处理,错误可以通过getsockopt指定SO_ERROR选项来获取。

参数4:异常集合,关心异常事件;

套接口存在带外数据(TCP头部 URG标志,16位紧急指针字段)

参数5:超时时间结构体

对于参数2,3,4来说,如果不关心对应事件则设置为NULL即可。注意5个参数都是输入输出参数,即select返回时可能对其进行了修改,比如集合被修改以便标记哪些套接口发生了事件,时间结构体的传出参数是剩余的时间,如果设置为NULL表示永不超时。用select管理多个I/O,select阻塞等待,一旦其中的一个或多个I/O检测到我们所感兴趣的事件,select函数返回,返回值为检测到的事件个数,并且返回哪些I/O发送了事件,遍历这些事件,进而处理事件。注意当select阻塞返回后,此时调用accept
接收连接是不会阻塞的,直接返回已连接套接字,可以认为是select
提前阻塞了。但此时调用write 还是可能阻塞的,因为需要写入的空间大小可能缓冲区还不满足。

下面是4个可以对集合进行操作的宏:
void FD_CLR(int fd, fd_set *set); // 清除出集合
int  FD_ISSET(int fd, fd_set *set); // 判断是否在集合中
void FD_SET(int fd, fd_set *set); // 添加进集合中
void FD_ZERO(fd_set *set); // 将集合清零

RETURN VALUE
       On success, select() return the number of file descriptors contained in the three returned descriptor sets (that is,
       the total number of bits that are set in readfds, writefds,
exceptfds) which may be zero if the timeout  expires  before  anything
       interesting  happens.   On error, -1 is returned, and errno is
set appropriately; the sets and timeout become undefined, so do not
       rely on their contents after an error.

select 函数的举例应用看这里

参考:

《Linux C 编程一站式学习》

《TCP/IP详解 卷一》

《UNP》

五种I/O模型和select函数简介的更多相关文章

  1. 转:五种I/O模型和select函数简介

    源地址:http://blog.csdn.net/jnu_simba/article/details/9070955 一.五种I/O模型 1.阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调 ...

  2. 五种I/O 模式,select、epoll方法的理解,BIO、NIO、AIO理解 相关文章

    一.io方式 Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式——阻塞(默认IO模式),非阻 ...

  3. IO五种模型和select与epoll工作原理(引入nginx)

    用户速度体验的1-3-10原则 性能影响 有很多研究都表明,性能对用户的行为有很大的影响: 79%的用户表示不太可能再次打开一个缓慢的网站 47%的用户期望网页能在2秒钟以内加载 40%的用户 ...

  4. 比较一下Linux下的Epoll模型和select模型的区别

    一. select 模型(apache的常用) 1. 最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Sel ...

  5. select()函数 的学习

    select()的介绍 全是拷贝的如下文章: https://www.cnblogs.com/wenqiang/p/5508541.html select()函数的用例代码摘录如下文章: https: ...

  6. 面试中常问的五种IO模型和BIO,NIO,AIO

    一,五种IO模型: 一个IO操作可以分为两个步骤:发起IO请求和实际的IO操作例如:1.操作系统的一次写操作分为两步:第一步,将数据从用户空间拷贝到系统空间:第二步,从系统空间往网卡写.2.一次读操作 ...

  7. 04: 事件驱动、五种I/O操作、I/O多路复用select和epoll

    网络编程其他篇 目录: 1.1 事件驱动 1.2 五种I/O操作 1.3 I/O 多路复用之select.poll.epoll详解 1.1 事件驱动返回顶部 1.什么是事件驱动  定义:就是根据不同事 ...

  8. mysql中select五种子句和统计函数

    select 五种子句顺序 where 条件 group by 分组 having 把结果进行再次筛选 order by  排序 limit  取出条目 统计函数  max(列名)  求最大 min( ...

  9. linux第7天 I/O的五种模型, select

    服务器端避免僵尸进程的方法: 1)通过忽略SIGCHLD信号,解决僵尸进程 signal(SIGCHLD, SIG_IGN) 2)通过wait方法,解决僵尸进程 signal(SIGCHLD, han ...

随机推荐

  1. Python爬虫之selenium爬虫,模拟浏览器爬取天猫信息

    由于工作需要,需要提取到天猫400个指定商品页面中指定的信息,于是有了这个爬虫.这是一个使用 selenium 爬取天猫商品信息的爬虫,虽然功能单一,但是也算是 selenium 爬虫的基本用法了. ...

  2. C#中属性PropertyInfo的使用

    昨天编程遇到一个问题两个类字段都是二十多个,其中有十多个是相同的,需要将一个类的字段赋值给另外一个类,开始的自己想手动的一个个去赋值,后来想来一下C#基础知识,用PropertyInfo就可以解决类似 ...

  3. Git的简单介绍

    每次看到别人写Git的文章,同学中也有用Git感觉很高大上的感觉,工作中用的是SVN,周末倒腾了一下Git,Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git 与 ...

  4. magento upsell from cur_category

    <?php /** * Magento * * NOTICE OF LICENSE * * This source file is subject to the Academic Free Li ...

  5. 应用程序在状态栏展示时间(C#)

    private DispatcherTimer _timer; private void SetTimeElaspInStatusBar() { try { _timer = new Dispatch ...

  6. sqoop安装部署(笔记)

    sqoop是一个把关系型数据库数据抽向hadoop的工具.同时,也支持将hive.pig等查询的结果导入关系型数据库中存储.由于,笔者部署的hadoop版本是2.2.0,所以sqoop的版本是:sqo ...

  7. IMA文件如何打开,winimage使用方

    一般先用UltraISO打开一个系统的镜像文件(.iso).其中有些文件(尤其是.ima,img)比如下面雨林木风Ghost系统盘的这个IMA文件,我们先提取到桌面 用WinImage打开这个文件即可 ...

  8. photoshop 去掉gif水印

    先贴上未去除水印的GIF图片!~ 打开选中需要处理的“gif文件” 下面就以动图给大家介绍一下: 首先勾选 时间轴和图层 第二步(选择区域) 第三步(选择水印区域),选择完了以后按Enter 选中第一 ...

  9. 【React Native开发】React Native控件之ListView组件解说以及最齐全实例(19)

    ),React Native技术交流4群(458982758).请不要反复加群!欢迎各位大牛,React Native技术爱好者加入交流!同一时候博客左側欢迎微信扫描关注订阅号,移动技术干货,精彩文章 ...

  10. alipay

    //安装 插件cordova plugin add https://github.com/charleyw/cordova-plugin-alipay.git --variable PARTNER_I ...