http://blog.chinaunix.net/uid-25324849-id-247813.html

1. I/O模型 
Unix下共有五种I/O模型 
a. 阻塞I/O 
b. 非阻塞I/O 
c. I/O复用(select和poll) 
d. 信号驱动I/O(SIGIO) 
e. 异步I/O(Posix.1的aio_系列函数) 
1). 阻塞I/O模型 
应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 
如果数据没有准备好,一直等待。。。。 
数据准备好了,从内核拷贝到用户空间 
I/O函数返回成功指示

2). 非阻塞I/O模型 
我们把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试 数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。

3). I/O复用模型 
I/O复用模型会用到select或者poll函数,这两个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。 

4). 信号驱动I/O模型 
首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

5). 异步I/O模型 
调用aio_read函数,告诉内核描述字,缓冲区指针,缓冲区大小,文件偏移以及通知的方式,然后立即返回。当内核将数据拷贝到缓冲区后,再通知应用程序。

2. 几种I/O模型的比较 
前四种模型的区别是第一阶段基本相同,第二阶段基本相同,都是将数据从内核拷贝到调用者的缓冲区。而异步I/O的两个阶段都不同于前四个模型。

3. 同步I/O和异步I/O 
a. 同步I/O操作引起请求进程阻塞,直到I/O操作完成。 
异步I/O操作不引起请求进程阻塞。 
b. 我们的前四个模型都是同步I/O,只有最后一个异步I/O模型是异步I/O。

部分内容来自:http://blog.csdn.net/sunyubo458/archive/2010/12/24/6096723.aspx

4. Select函数 
a. Select函数可以指示内核等待多个事件中的任一个发生,并仅在任一个事件发生或经某个指定的时间后才返回,才唤醒进程 
b. 可以调用select函数,通知内核在下列情况发生时才返回: 
集合{1,4,5}中的任何描述符准备好读,或者 
集合{2,7}中的任何描述符准备好写,或者 
集合{1,4}中任何描述符有异常条件待处理,或者 
已经经过了10.2秒 
c.描述字可以不受限制与套接字,任意的描述符都可以用select来测试 
d. 函数原型 
int select(int maxfds, fd_set *readfds, fd_set *writefds, 
      fd_set *exceptfds, struct tim *timeout); 
参数说明: 
timeout:告诉内核等待任一描述符准备好可以花费的时间,这里会有三种情况, 
第一种情况是timeout是NULL,这样将一直等待,直到某个描述符准备好; 
第二种情况是timeout的值是0,那么将不等待,立即返回; 
第三种情况是timeout中的秒或微秒被赋值,那么将等待指定的时间。 
此外,如果进程收到一个信号,select也会被中断返回。 
readfds,writefds和exceptfds指定了让内核测试读,写和异常条件所需的描述字。 
maxfds:说明了被测试的描述符的个数,它的值是要被测试的最大的描述符加1. 
返回值:所有描述符集的已准备好的总位数。返回时,描述符集中任何没有准备好的描述符都被清0,我们用FD_ISSET来测试是哪个描述符准备好了。因此,每次调用select时,都要重新将我们关心的描述符在描述符集中置为1. 
e. fd_set说明 
fd_set是一个整数数组,每个数中的每一位对应一个描述符。例如用32位表示一个整数,那么数组的第一个元素对应于描述字0~31,第二个元素对应于描述字32~63. 
四个相关的宏: 
       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); 
f.描述符准备好读的条件: 
套接口缓冲区中的数据字节大于等于套接口接收缓冲区低潮限度的当前值。套接口将不阻塞并返回一个大于0的值,就是当前准备好读的数据字节数。 
套接口收到一个FIN,套接口的读操作将返回一个0. 
套接口是一个监听套接口,并且以完成的连接数非0。 
有一个套接口错误待处理。套接口的读操作将返回-1. 
g.描述符准备好写的条件: 
套接口发送缓冲区的可用空间大于等于套接口发送缓冲区低潮限度的当前值。,且或者套接口以连接,套接口不要求连接。 
套接口写这一半关闭,这样将产生一个SIGPIPE错误。 
有一个套接口错误待处理。 
h.描述符异常的条件: 
套接口存在带外数据 
仍处于带外标记 
i. 每个进程可以使用的最大描述符 
有一个宏FD_SETSIZE定义了一个进程可以使用的最大描述符数。如果要更改这个值不仅仅要在定义的头文件中改变,还要重新编译内核。

5. 使用select函数修改前面的客户-服务器程序 
在前面的客户-服务器程序中,客户端采用的是停-等这样的策略来接收来自标准输入的用户输入,这样的好处是可以一对一的完成从用户输入,然后读取从服务器 返回的字符串,这样的弊端是当程序阻塞在等待用户输入时,无法及时的处理来自服务器的FIN等这些消息。现在我们用select函数将客户端程序做一些修 改,使能避免前面提到的问题。 
另外,服务器也采用select函数,从而避免产生过多的进程,使用select后可以只有一个进程就可以处理多个客户端。在服务器端建立一个整数型的数 组,用来存放已经完成的客户端连接。每次从见天套接口读到数据后,我们将新的来自客户端的连接加入到这个数组中,并且修改maxfd的值。每次从客户端套 接口读到数据后,将读到的数据重新写回到客户端套接口。 
a.服务器从客户套接口读到数据后,返回值有可能为0,这说明客户端已经关闭了写这个方向的连接。在将数据写入客户端套接口后,要将连接关闭。并将客户连接从存放客户连接的数组中移除。 
b.采用上面的方案,存在一个潜在的问题就是可能受到拒绝服务的攻击。一个恶意用户和服务器建立连接,发送单个字符,但是没有发送换行符或者终止,这样服 务器将阻塞在read函数中。可能的解决办法是采用非阻塞I/O或者让每个客户用单独的进程来处理或者为I/O操作设置超时。 
c.客户端接收到EOF时,只能关闭写这个方向的连接,因为我们仍然希望读取来自服务器的数据。此时是不能用close来关闭连接的,而要用 shutdown来关闭。如果套接字的访问计数大于0,那么close只是将计数减1;如果套接字的访问计数等于0,close将终止套接字的两个方向, 那样我们将不能读取仍然没有从服务器发送回来的数据。 
6. shutdown函数 
int shutdown(int s, int how); 
参数说明: 
s: 代表套接字描述字 
how:SHUT_RD    -- 关闭套接字的读取数据方向的连接 
     SHUT_WR    -- 关闭套接字的写入数据方向的连接 
     SHUT_RDWR -- 关闭套接字双向的连接 
7. pselect函数 
int pselect(int n, fd_set *readfds, fd_set *writefds, 
      fd_set *exceptfds, const struct timespec *timeout, const 
      sigset_t *sigmask); 
a.pselect函数采用timespec结构,这个结构支持纳秒 
b.sigmask是信号掩码,将禁止递交某些信号 
8. poll函数 
int poll(struct pollfd *ufds, unsigned int nfds, int timeout); 
a.参数说明 
ufds: 是一个struct pollfd结构体的指针 
nfds: 说明我们关心的描述字的个数 
timeout: 超时等待的时间,单位是毫秒 
b.struct pollfd结构体说明 
       struct pollfd { 
             int fd;          
             short events;    
             short revents;   
      }; 
fd: 是描述字 
events: 是在描述字上关心的事件 
revents: 是在描述字上返回的事件

poll函数返回后我们要测试revents中的事件是否是我们关心的。

Unix下五种IO模型的更多相关文章

  1. 2018.5.4 Unix的五种IO模型

    阻塞非阻塞和异步同步 同步和异步关注的是消息通信机制,关注两个对象之间的调用关系. 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态,关注单一程序. Unix的五种IO模型 以下基于Li ...

  2. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  3. Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  4. Linux 下的五种 IO 模型

    概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的 ...

  5. 聊聊 Linux 中的五种 IO 模型

    本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451 ...

  6. 五种IO模型

    参考文档 https://www.jianshu.com/p/486b0965c296 概念说明 用户空间和内核空间        现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空 ...

  7. 漫谈五种IO模型

    阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,搞清楚这些概念之前,还得先回顾一些基础的概念. 1 基础知识回顾 注意 ...

  8. Atitit  五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I

    Atitit  五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I   1.1. .3 进程的阻塞1 1.2. 网络 ...

  9. [转载] Linux五种IO模型

      转载:http://blog.csdn.net/jay900323/article/details/18141217     Linux五种IO模型性能分析   目录(?)[-] 概念理解 Lin ...

随机推荐

  1. Linq语法学习

    关键词: select from where in into join on equals orderby descending DefaultIfEmpty() thenby submitChang ...

  2. MVC中使用内建的HTML辅助方法产生表单元素提交表单与button按钮事件的陷阱

    网站模板页有个登陆的退出按钮,当点击时跳转到登陆页面. <button onclick="logout()" >退出</button> $("#l ...

  3. const 不再迷茫

    博客地址:http://blog.csdn.net/jiangxinnju github:https://github.com/jiangxincode 首先说明一下const在C和C++中的主要用法 ...

  4. 未打开Ad Hoc Distributed Queries

    SSAS访问ORACLE数据仓库读取数据创建CUBE的时候报如下错误: SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT 'Open ...

  5. Stash安装和破解

    参考资料: http://www.unxmail.com/?p=590 上篇介绍了,Atlassian Stash v2.12.1 破解版的下载, 有同学不会安装. 我重新整理了下文档. 表述我的安装 ...

  6. IMDB TOP 250爬虫

    这个小学期Python大作业搞了个获取IMDB TOP 250电影全部信息的爬虫.第二次写爬虫,比在暑假集训时写的熟练多了.欢迎大家评论. ''' ************************** ...

  7. LOJ6000 - 「网络流 24 题」搭配飞行员

    原题链接 题意简述 求二分图的最大匹配. 题解 这里写的是匈牙利算法. 表示节点的当前匹配. 为真表示在这一轮匹配中,无法给节点一个新的匹配.所以如果为真就不用再dfs它了,直接continue就好. ...

  8. Maven把项目依赖的所有jar包都打到同一个jar中

    目录 1 使用maven-shade-plugin 2 推荐: 使用maven-assembly-plugin 3 扩展: Maven安装本地jar包到本地仓库 4 扩展: 手动生成jar包 5 扩展 ...

  9. 关于U3D的.SDK对接

    1,SDK对接原理:https://www.cnblogs.com/msxh/p/7220741.html 2,Unity ADS对接:https://blog.csdn.net/chenluwolf ...

  10. python - 发送带各种类型附件的邮件

    如何发送各种类型的附件. 基本思路就是,使用MIMEMultipart来标示这个邮件是多个部分组成的,然后attach各个部分.如果是附件,则add_header加入附件的声明. 在python中,M ...