源地址:http://blog.csdn.net/jnu_simba/article/details/9070955

一、五种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的实现或多或少存在问题,用得也比较少。

二、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阻塞返回后,此时调用read/write 是不会阻塞的,因为正是有可读可写事件发生才导致select 返回,也可以认为是select 提前阻塞了。
下面是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); // 将集合清零

select函数的举例应用看这里

参考:

《Linux C 编程一站式学习》

《TCP/IP详解 卷一》

《UNP》

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

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

    一.五种I/O模型 1.阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核空间(套接口缓冲区)拷贝到用户空间(recv函数提 ...

  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. mysql中select五种子句和统计函数

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

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

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

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

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

随机推荐

  1. Spring MVC @RequestMapping注解详解(2)

    @RequestMapping 参数说明 value:定义处理方法的请求的 URL 地址.(重点) method:定义处理方法的 http method 类型,如 GET.POST 等.(重点) pa ...

  2. Qt学习笔记----基础知识

    一.qt的本质 qt的本质是c++的图形界面类库,本身是mvc结构.qt能火最大程度 归功于它跨平台的特性,一次编码,多次编译应用. 注意:qt由于历史原因,经历了奇趣.诺基亚.digit公司,导致q ...

  3. Java面试(1)

    一.Java基础 什么是字符串常量池? Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池: String是java中比较特殊的类,我们可以使用new运算符创建Str ...

  4. jquery.js和jquery.min.js的区别和springboot整合echarts.min.js

    1.区别:jquery官网提供2种jQuery的下载,一种是jquery.js另一种是jquery.min.js文件名不一定完全相同,但通常情况下:jquery.js是完整的未压缩的jQuery库,文 ...

  5. RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)

    1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...

  6. Android开发 ImageView开发记录

    改变图片的着色 默认是这个方法 /** * 为图像设置着色选项. Assumes * {@link PorterDuff.Mode#SRC_ATOP} blending mode. * * @para ...

  7. GCRoots 对象

    GC Roots 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中的类静态属性引用的对象 方法区中的常量引用的对象 原生方法栈(Native Method Stack)中 JNI 中引用的对象 可 ...

  8. CSS——before和after伪元素

    之所以被称为伪元素,是因为他们不是真正的页面元素,html没有对应的元素,但是其所有用法和表现行为与真正的页面元素一样,可以对其使用诸如页面元素一样的css样式,表面上看上去貌似是页面的某些元素来展现 ...

  9. MySQL 知识点随记

    1.存储过程中声明变量要在程序的最前面,也要在声明事务开始的前,不然会报错 2.Mysql 获取32位guid: REPLACE(UUID(),"-","") ...

  10. flink提交文件出现java.io.IOException:unable to close file because the last block does not have enough number of replicas异常

    当提交已经打包好的jar包时候,控制台出现以下的错误.