IO模式的选择

五种IO模式
    阻塞IO
    非阻塞IO
    IO多路复用
    信号驱动IO
    异步IO
一般来说,程序进行输入操作有两步:
1.等待有数据可以读
2.将数据从系统内核中拷贝到程序的数据区。
对于一个对套接字的输入操作,第一步一般来说是等待数据从网络上传到本地。当数
据包到达的时候,数据将会从网络层拷贝到内核的缓存中;第二步是从内核中把数据拷贝
到程序的数据区中。
 
几种I/O 模式的比较
 阻塞模式 非阻塞模式多路复用 信号驱动     异步

   初始化
    |
    |
    |
    |
    |
    |
    |   
    |
    |
    V
   结束

    检查
    检查
    检查
    检查
    检查
    检查
    检查
    检查
    检查
    结束
    检查
    就绪
   初始化
    结束

   检查
    |
    |
  阻|
  塞|
    |
    |
    |
    V
   就绪
  初始化
    |
    V
   结束

   
   
   
   
   
   
   
   
  信号通知
   初始化
     |
     V
   初始化
    结束

   初始化
   
   
   
   
   
   
   
   
   
   
   
   
  信号通知
 

使用场景说明:

阻塞IO

阻塞I/O 模式是最普遍使用的I/O 模式。大部分程序使用的都是阻塞模式的I/O 。缺
省的,一个套接字建立后所处于的模式就是阻塞I/O 模式。
对于一个UDP 套接字来说,数据就绪的标志比较简单:
l 已经收到了一整个数据报
l 没有收到。
而TCP 这个概念就比较复杂,需要附加一些其他的变量。
    一个进程调用recvfrom ,然后系统调用并不返回知道有数据报到达本地
系统,然后系统将数据拷贝到进程的缓存中。(如果系统调用收到一个中断信号,则它的
调用会被中断)
我们称这个进程在调用recvfrom 一直到从recvfrom 返回这段时间是阻塞的。当recvfrom
正常返回时,我们的进程继续它的操作。

非阻塞IO

当我们将一个套接字设置为非阻塞模式,我们相当于告诉了系统内核:“当我请求的
I/O 操作不能够马上完成,你想让我的进程进行休眠等待的时候,不要这么做,请马上返
回一个错误给我。”

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

IO多路复用

    当一个客户端需要同时处理多个文件描述符的输入输出操作的时候(一般来说是
标准的输入输出和网络套接字), I/O 多路复用技术将会有机会得到使用。
    当程序需要同时进行多个套接字的操作的时候。
如果一个TCP 服务器程序同时处理正在侦听网络连接的套接字和已经连接好的套
接字。
    如果一个服务器程序同时使用TCP 和UDP 协议。
    如果一个服务器同时使用多种服务并且每种服务可能使用不同的协议(比如inetd
就是这样的)。
I/O 多路服用技术并不只局限与网络程序应用上。几乎所有的程序都可以找到应用I/O
多路复用的地方。

    在使用I/O 多路技术的时候,我们调用select()函数和poll()函数,在调用它们的时候
阻塞,而不是我们来调用recvfrom(或recv)的时候阻塞。

信号驱动IO

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

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

信号驱动对TCP 套接字而言没有什么作用。因为对于一个TCP 套接字来说, SIGIO 信号发生的几率太高了,所以SIGIO 信号并不能告诉我们究竟发生了什么事情。

异步I/O 模式


当我们运行在异步I/O 模式下时,我们如果想进行I/O 操作,只需要告诉内核我们要
进行I/O 操作,然后内核会马上返回。具体的I/O 和数据的拷贝全部由内核来完成,我们
的程序可以继续向下执行。当内核完成所有的I/O 操作和数据拷贝后,内核将通知我们的
程序。
异步I/O 和 信号驱动I/O 的区别是:
    信号驱动I/O 模式下,内核在操作可以被操作的时候通知给我们的应用程序发送
SIGIO 消息。
    异步I/O 模式下,内核在所有的操作都已经被内核操作结束之后才会通知我们的
应用程序。

<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
阅读(896) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值