五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O

五种I/O 模式:
【1】        阻塞 I/O           (Linux下的I/O操作默认是阻塞I/O,即open和socket创建的I/O都是阻塞I/O)
【2】        非阻塞 I/O        (可以通过fcntl或者open时使用O_NONBLOCK参数,将fd设置为非阻塞的I/O)
【3】        I/O 多路复用     (I/O多路复用,通常需要非阻塞I/O配合使用)
【4】        信号驱动 I/O    (SIGIO)
【5】        异步 I/O

一般来说,程序进行输入操作有两步:
1.等待有数据可以读
2.将数据从系统内核中拷贝到程序的数据区。

对于sock编程来说:

第一步:   一般来说是等待数据从网络上传到本地。当数据包到达的时候,数据将会从网络层拷贝到内核的缓存中;

第二步:   是从内核中把数据拷贝到程序的数据区中。

阻塞I/O模式                            //进程处于阻塞模式时,让出CPU,进入休眠状态
        阻塞 I/O 模式是最普遍使用的 I/O 模式。是Linux系统下缺省的IO模式。

大部分程序使用的都是阻塞模式的 I/O 。

一个套接字建立后所处于的模式就是阻塞 I/O 模式。(因为Linux系统默认的IO模式是阻塞模式)

对于一个 UDP 套接字来说,数据就绪的标志比较简单:
(1)已经收到了一整个数据报
(2)没有收到。
而 TCP 这个概念就比较复杂,需要附加一些其他的变量。

一个进程调用 recvfrom  ,然后系统调用并不返回知道有数据报到达本地系统,然后系统将数据拷贝到进程的缓存中。 (如果系统调用收到一个中断信号,则它的调用会被中断)

我们称这个进程在调用recvfrom一直到从recvfrom返回这段时间是阻塞的。当recvfrom正常返回时,我们的进程继续它的操作。

非阻塞模式I/O                           //非阻塞模式的使用并不普遍,因为非阻塞模式会浪费大量的CPU资源。
       当我们将一个套接字设置为非阻塞模式,我们相当于告诉了系统内核: “当我请求的I/O 操作不能够马上完成,你想让我的进程进行休眠等待的时候,不要这么做,请马上返回一个错误给我。”
      我们开始对 recvfrom 的三次调用,因为系统还没有接收到网络数据,所以内核马上返回一个 EWOULDBLOCK的错误。

第四次我们调用 recvfrom 函数,一个数据报已经到达了,内核将它拷贝到我们的应用程序的缓冲区中,然后 recvfrom 正常返回,我们就可以对接收到的数据进行处理了。
      当一个应用程序使用了非阻塞模式的套接字,它需要使用一个循环来不听的测试是否一个文件描述符有数据可读(称做 polling(轮询))。应用程序不停的 polling 内核来检查是否 I/O操作已经就绪。这将是一个极浪费 CPU资源的操作。这种模式使用中不是很普遍。

 例如:
         对管道的操作,最好使用非阻塞方式!
 

I/O多路复用                             //针对批量IP操作时,使用I/O多路复用,非常有好。

       在使用 I/O 多路技术的时候,我们调用 select()函数和 poll()函数或epoll函数(2.6内核开始支持),在调用它们的时候阻塞,而不是我们来调用 recvfrom(或recv)的时候阻塞。
       当我们调用 select函数阻塞的时候,select 函数等待数据报套接字进入读就绪状态。当select函数返回的时候, 也就是套接字可以读取数据的时候。 这时候我们就可以调用 recvfrom函数来将数据拷贝到我们的程序缓冲区中。
        对于单个I/O操作,和阻塞模式相比较,select()和poll()或epoll并没有什么高级的地方。
        而且,在阻塞模式下只需要调用一个函数:
                             读取或发送函数。
                   在使用了多路复用技术后,我们需要调用两个函数了:
                             先调用 select()函数或poll()函数,然后才能进行真正的读写。

多路复用的高级之处在于::

它能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select()函数就可以返回。

IO 多路技术一般在下面这些情况中被使用:
1、当一个客户端需要同时处理多个文件描述符的输入输出操作的时候(一般来说是标准的输入输出和网络套接字),I/O 多路复用技术将会有机会得到使用。
2、当程序需要同时进行多个套接字的操作的时候。
3、如果一个 TCP 服务器程序同时处理正在侦听网络连接的套接字和已经连接好的套接字。
4、如果一个服务器程序同时使用 TCP 和 UDP 协议。
5、如果一个服务器同时使用多种服务并且每种服务可能使用不同的协议(比如 inetd就是这样的)。
  
异步IO模式有::
       1、信号驱动I/O模式
       2、异步I/O模式
信号驱动I/O模式                                                   //自己没有用过。

我们可以使用信号,让内核在文件描述符就绪的时候使用 SIGIO 信号来通知我们。我们将这种模式称为信号驱动 I/O 模式。

为了在一个套接字上使用信号驱动 I/O 操作,下面这三步是所必须的。
(1)一个和 SIGIO信号的处理函数必须设定。
(2)套接字的拥有者必须被设定。一般来说是使用 fcntl 函数的 F_SETOWN 参数来
进行设定拥有者。
(3)套接字必须被允许使用异步 I/O。一般是通过调用 fcntl 函数的 F_SETFL 命令,O_ASYNC为参数来实现。

虽然设定套接字为异步 I/O 非常简单,但是使用起来困难的部分是怎样在程序中断定产生 SIGIO信号发送给套接字属主的时候,程序处在什么状态。

1.UDP 套接字的 SIGIO 信号                    (比较简单)
在 UDP 协议上使用SIGIO 非常简单.这个信号将会在这个时候产生:
1、套接字收到了一个数据报的数据包。
2、套接字发生了异步错误。
        当我们在使用 UDP 套接字异步 I/O 的时候,我们使用 recvfrom()函数来读取数据报数据或是异步 I/O 错误信息。
2.TCP 套接字的 SIGIO 信号                      (因为复杂,实际一般用的是socket的异步IO)
          不幸的是,SIGIO 几乎对 TCP 套接字而言没有什么作用。因为对于一个 TCP 套接字来说,SIGIO 信号发生的几率太高了,所以 SIGIO 信号并不能告诉我们究竟发生了什么事情。
在 TCP 连接中, SIGIO 信号将会在这个时候产生:
l  在一个监听某个端口的套接字上成功的建立了一个新连接。
l  一个断线的请求被成功的初始化。
l  一个断线的请求成功的结束。
l  套接字的某一个通道(发送通道或是接收通道)被关闭。
l  套接字接收到新数据。
l  套接字将数据发送出去。

l  发生了一个异步 I/O 的错误。

一个对信号驱动 I/O 比较实用的方面是 NTP(网络时间协议 Network Time Protocol)服务器,它使用 UDP。这个服务器的主循环用来接收从客户端发送过来的数据报数据包,然后再发送请求。对于这个服务器来说,记录下收到每一个数据包的具体时间是很重要的。

因为那将是返回给客户端的值,客户端要使用这个数据来计算数据报在网络上来回所花费的时间。图 6-8 表示了怎样建立这样的一个 UDP 服务器。

异步I/O模式             //比如写操作,只需用写,不一定写入磁盘(这就是异步I/O)的好处。异步IO的好处效率高。
      当我们运行在异步 I/O 模式下时,我们如果想进行 I/O 操作,只需要告诉内核我们要进行 I/O 操作,然后内核会马上返回。具体的 I/O 和数据的拷贝全部由内核来完成,我们的程序可以继续向下执行。当内核完成所有的 I/O 操作和数据拷贝后,内核将通知我们的程序。
异步 I/O 和  信号驱动I/O的区别是:
        1、信号驱动 I/O 模式下,内核在操作可以被操作的时候通知给我们的应用程序发送SIGIO 消息。

2、异步 I/O 模式下,内核在所有的操作都已经被内核操作结束之后才会通知我们的应用程序。

 
 
 

五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O的更多相关文章

  1. Linux IO模式-阻塞io、非阻塞io、多路复用io

    一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...

  2. 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  3. Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO

    背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...

  4. 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

  5. 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...

  6. 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO

    完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...

  7. 事件驱动模型 IO多路复用 阻塞IO与非阻塞IO select epool

    一.事件驱动 1.要理解事件驱动和程序,就需要与非事件驱动的程序进行比较.实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的.早期则存在许多非事件驱动的程序,这样的程序,在需要等待 ...

  8. python网络编程-同步IO和异步IO,阻塞IO和非阻塞IO

    同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. ...

  9. 阻塞IO、非阻塞IO的区别

    1.类与类之间的关系:依赖,实现,泛化(继承),关联,组合,聚合. 1)依赖(虚线):一个类是 另一个类的函数参数 或者 函数返回值. 2)实现(实线加小圆):对纯虚函数类(抽象类)的实现. 3)继承 ...

  10. 阻塞IO、非阻塞IO、同步IO、异步IO等

    https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...

随机推荐

  1. 为什么objc_msgSend必须用汇编实现

    译者前言 总是看到有人说用汇编实现objc_msgSend是为了速度快,当然这个不可否认.但是难道没有别的原因?于是就看到了这篇文章,遂翻译之!=.= 我自己的理解就是,用汇编实现,是为了应对不同的“ ...

  2. [原创] Fragment的添加、移除问题

    安卓一直在进化,Fragment就是个好东西,如果早5年做安卓开发,真要麻烦的多. 关于Fragment的讲解,这里很详尽: Android Fragment 真正的完全解析(上) Android F ...

  3. 给sqlserver配置内存参数

    操作环境:windows server 2003 R2 Enterprise Edition SP1 + 4G 内存 + Sqlsever 2005 在以上环境中,运行公司的ERP数据服务,sqlse ...

  4. Nagios新添加的hosts和services有时显示,有时不显示问题解决

    在nagios配置文件hosts.cfg和services.cfg中添加了新服务器和服务列表,重启nagios服务后刷新监控页面,新添加的服务器和服务列表有时能显示出来,有时又显示不出来. 解决方法: ...

  5. 【BZOJ2653】【主席树+二分】middle

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

  6. Python中%s和%r的区别

    早先使用Python工作的时候,对于格式化输出%s和%r的使用都是混着用的. 这一次就出错了: cu.execute("insert into ipPool values(null, '%r ...

  7. ng的数据绑定

    ng创建了一个自己的事件循环,当浏览器事件(常用的dom事件,xhr事件等)发生时,对DOM对应的数据进行检查,若更改了,则标记为脏值,并进入更新循环,修改对应的(可能是多个) DOM的参数.这样就实 ...

  8. 通用方法解决dedecms导航调用二级、三级栏目菜单

    博客之前做网站的时候经常会遇到二级菜单.三级菜单.了解dede的人都知道从5.5版本开始都有二级菜单的调用方法了,网上也有不少的教程文章.不过这个调用需要修改dede源码的二级菜单样式.个人感觉不是很 ...

  9. C语言陷阱——类型转换

    以下例子取自<深入理解计算机系统>. 考虑如下的C语言代码: #include<stdio.h> typedef unsigned char* byte_pointer; vo ...

  10. WWDC2014之iOS使用动态库

    苹果的开放态度 WWDC2014上发布的Xcode6 beta版有了不少更新,其中令我惊讶的一个是苹果在iOS上开放了动态库,在Xcode6 Beta版的更新文档中是这样描述的: Frameworks ...