前言

看过很多资料,很多对I/O模型概念模糊甚至错误,希望这篇文章有助理解I/O,欢迎讨论和纠正

参考资料:《UNIX网络编程卷1》  P122

I/O中涉及概念

介绍阻塞非阻塞,同步异步之前,先分析一下I/O请求过程

  1. 等待数据准备好
  2. 从内核向进程复制数据

过程1决定是否阻塞,过程2决定是否同步

误区1:不要以为是否阻塞和是否同步会排列组合成4中状态,实际上只有三种:同步阻塞,同步非阻塞,异步非阻塞(一般来说异步非阻塞就成为异步,都异步了还阻塞啥?很多资料竟然还扯异步阻塞)

那么究竟什么是同步异步,阻塞非阻塞?

同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由*调用者*主动等待这个*调用*的结果。

而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

总结

同步和异步说的是消息通知机制:同步的情况下,是由处理消息者自己去等待消息是否被触发,而异步的情况下是由触发机制来通知处理消息者

阻塞非阻塞说的是消息处理机制:

Unix可用的5中I/O模型:

  • 阻塞式I/O
  • 非阻塞式I/O
  • I/O复用(select和poll)
  • 信号驱动式I/O(SIGIO)
  • 异步I/O(POSIX的aio_系列函数)

生活中的例子

我经常和同学去吃庆丰包子,从点餐开始就出现了I/O模型

我:应用程序

前台:内核

点餐:I/O请求

阻塞式I/O:我去前台点餐(I/O请求),点玩后站那毛都不干(等待数据,进程sleep),于此同时前台让后厨准备包子,后厨做好后给前台(数据准备好),我端着盘子去找位置坐下(复制数据)

非阻塞式I/O:我去前台点餐(I/O请求),点玩后站在那里无聊,就和朋友打电话(等待数据但进程没有sleep),但眼睛还是时不时扫一眼看看包子好没好(轮询内核),于此同时前台让后厨准备包子,后厨做好后给前台(数据准备好),我端着盘子去找位置坐下(复制数据)

I/O复用(select和poll):班里组织吃包子,4人一桌,班长说各位落座,我自己在前台等着通知大家,班长记录了一个纸条,上面是对应的桌子和点的餐(描述符集合),他在前台等着谁的包子做好了就叫谁,被叫到的同学端着盘子回到座位(复制数据)

信号驱动式I/O:事实上这种才是庆丰包子铺的做法,我我去前台点餐(I/O请求),服务员给我一个号码,然后我落座跟同学吹牛逼,一会服务员叫到38号你的包子好了(信号),我就屁颠屁颠跑到前台把包子端回来(复制数据)

异步I/O:(POSIX的aio_系列函数):由于常去庆丰吃包子,我成为了VIP用户。这天我去前台点餐(I/O请求),然后我落座跟同学吹牛逼,吹到一半包子好了,但是服务员也没叫我(事实上我都不知道包子好了这件事),我还在继续吹牛逼,服务员这时把包子端上来了(复制数据由内核完成了)。这实际上是饭点常用的做法

总结:等待包子做好的过程是等待数据,等待过程中你是挂起还是搞基(是否sleep)决定了是否阻塞;包子准备好了,是你自己去取还是让服务员给你拿来决定了是否是异步,事实上如果你选择让服务员给你拿来(异步),也就没必要看着盯着前台看看包子是否做好了,因为你不用关心是否做好了(因为好了后服务员给你拿过来),从这个角度去思考就知道为什么没有异步阻塞了

陈硕在知乎上的回答也印证了这一点:

阻塞式I/O

默认情况下,所有套接字都是阻塞的。从调用recvfrom开始到它返回的整段时间内是被阻塞的。recvfrom成功返回后,应用进程开始处理数据报

非阻塞式I/O

I/O复用(select和poll)

信号驱动式I/O(SIGIO)

这种模型的优势在于等待数据报到达期间进程不被阻塞,主循环可以继续执行

异步I/O

信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成

I/O模型比较

同步I/O操作:导致请求进程阻塞,直到I/O操作完成

异步I/O操作:不导致请求进程阻塞

前四种模型的主要区别在第一阶段,因为它们第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于recvfrom调用

异步I/O模型在这两个阶段都要处理,前四种都是同步,因为其中真正的I/O操作(recvfrom)将阻塞进程。只有异步I/O模型与POSIX定义的异步I/O相匹配

其它好的博客;

也谈同步异步I/O

select、poll、epoll之间的区别总结

Linux IO模式及 select、poll、epoll详解

可能是最接地气的 I/O 多路复用小结

Linux IO模式及 select、poll、epoll详解

刨根问底拦不住——I/O模型的更多相关文章

  1. Padrino 博客开发示例

    英文版出处:http://www.padrinorb.com/guides/blog-tutorial 楼主按 拿作者自己的话说:Padrino(谐音:派骓诺)是一款基于Sinatra的优雅的Web应 ...

  2. [置顶] 请听一个故事------>你真的认为iPhone只是一部手机?苹果惊天秘密!!

    在网上看到的一篇小说,感觉有点意思,转载过来大家一起围观下,作者很幽默很风趣. 导读:iPhone的隐藏功能!Jobs的军方身份!图灵服毒自杀的传奇故事!中兴华为的神秘背景! 你真的认为iPhone只 ...

  3. 关于ACM,关于CSU

    原文地址:http://tieba.baidu.com/p/2432943599 前言: 即将进入研二,ACM的事情也渐渐远去,记忆终将模糊,但那段奋斗永远让人热血沸腾.开个贴讲讲ACM与中南的故事, ...

  4. 正本清源区块链——Caoz

    正本清源区块链 说明:以下内容整理自Caoz的<正本清源区块链>,如有不妥,请联系我修改或删除. 简介 不讨论炒币!不讨论炒币!不讨论炒币! 本课程内容分为两部分: 第一部分,烧脑篇,介绍 ...

  5. iOS 动态化

    来自bang's blog http://blog.cnbang.net/tech/3286/ 问题 在开发模式上,web 的方式是比较先进的,有各种优点,包括跨平台/UI开发效率高,最重要的是可以时 ...

  6. Padrino 生成器指南

    英文版出处:http://www.padrinorb.com/guides/generators Padrino提供了用于快速创建应用的生成器,其优势在于构建推荐的Padrino应用结构.自动生成罗列 ...

  7. jQuery知识点总结(第四天)

    前三天是jQuery的基础部分,选择器学好了.才能进行下一步的操作,如果前三天没学过没学好,不要跳着学.粗俗的话叫做,步子大了,容易扯着蛋.一步一个脚印,是最好的方式. 强调一下.有问题,不要憋着不讲 ...

  8. 解决js(ajax)提交后端的“ _xsrf&#39; argument missing from POST” 的错误

    首先先简述一下CSRF: CSRF是Cross Site Request Forgery的缩写(也缩写为XSRF),直译过来就是跨站请求伪造的意思,也就是在用户会话下对某个CGI做一些GET/POST ...

  9. 如何调试Android Framework?

    Linus有一句名言广为人知:Read the fucking source code. 但其实,要深入理解某个软件.框架或者系统的工作原理,仅仅「看」代码是远远不够的.就拿Android Frame ...

随机推荐

  1. 子div设置float后导致父div无法自动撑开的问题

    子div设置float后会导致父div无法自动撑开 原因:内部的DIV因为float:left之后,就丢失了clear:both和display:block的样式,所以外部的DIV不会被撑开. 以下是 ...

  2. mongodb 启动脚本和配置

    http://justcoding.iteye.com/blog/2270466 http://blog.csdn.net/neutrojan/article/details/32328531

  3. ViewPager+GridView实现横向滑动 仿大众点评

    先看演示效果: 1  ViewPager类提供了多界面切换的新效果. 新效果有如下特征: [1] 当前显示一组界面中的其中一个界面. [2] 当用户通过左右滑动界面时,当前的屏幕显示当前界面和下一个界 ...

  4. IntelliJ IDEA 快捷键大全

    IntelliJ IDEA 快捷键大全 (2012-03-27 20:33:44) 转载▼ 标签: ide intellij快捷键 杂谈 分类: IDE工具 最近刚接触IntelliJ这个工具,用了几 ...

  5. Linux 忘记root登录密码解决方法

    很多朋友经常会忘记Linux系统的root密码,linux系统忘记root密码的情况该怎么办呢?重新安装系统吗?当然不用!进入单用户模式更改一下root密码即可. 步骤如下: 重启linux系统 3  ...

  6. Linux下/boot目录

    /boot目录存放的是开机所需的文件----内核,开机菜单,及所需配置文件等: (1)系统Kernel的配置文件: (2)启动管理程序GRUB的目录,里面放的都是GRUB在启动时所需要的画面.配置及各 ...

  7. PHP 使用reflection时的问题,以及解决方案

    错误:PHP Fatal error: Using $this when not in object context 代码如下: <?php class someClass { private ...

  8. java中使用split分割字符串一个有趣的现象

    最近在项目中,发现了一个bug,充分了展示了自己对java底层的认知有很多的不足和欠缺. 下面有段代码: String str="1#2#3"; String[] strs=str ...

  9. icon@font-face那些事

    http://files.cnblogs.com/files/LoveOrHate/font.rar @font-face { font-family: 'Glyphicons Regular'; s ...

  10. POJ 1054 The Troublesome Frog

    The Troublesome Frog Time Limit: 5000MS Memory Limit: 100000K Total Submissions: 9581 Accepted: 2883 ...