前言

看过很多资料,很多对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. 你真的认为iphone只是一部手机么

    闲言不表,直奔主题.我是一个程序员,上周参加了一个开源软件交流大会,其实会上并没有听到什么新鲜的东西.但是在会中,偶然间听到了一个关于iphone的秘密,却着实令我震惊了,事情具体是这样的,听我慢慢道 ...

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

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

  7. web笔记全

    1.项目流程与数据库 1.课程体系 阶段1(服务器开发): 项目导入/数据库/JS基础/NodeJS 阶段2(前端核心技术): HTML/AJAX/CSS/bootstrap 阶段3(前端进阶技术): ...

  8. 全国疫情精准定点动态更新(.net core)

    前言 疫情远比我们在年初想的发展迅速,在过年前还计划着可以亲戚聚聚,结果都泡汤了,开始了自家游. 在初三的时候,看到那个丁香医生,觉得不够详细,比如说我想看下周边城市的疫情情况,但是我地理不好,根本不 ...

  9. 常见web中间件漏洞(三)Nginx漏洞

    nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,有  开源,内存占用少,并发能力强,自由模块化,支持epoll模型,可限制连接数,支持热部署,简单 ...

随机推荐

  1. 【Mysql】 my.ini配置一例

    # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.6/en/server-co ...

  2. 加密算法使用(三):用用BASE64

    采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到 package testEncrypt; import java.security.Key; import java.secu ...

  3. PHP基础14:表单处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 反射中getMethods 与 getDeclaredMethods 的区别

    public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法.public Method[] getDeclar ...

  5. java.util.ConcurrentModificationException 解决办法

    在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除. 则使用会报以下异常:Java.util.ConcurrentModific ...

  6. linux实践——ELF分析

    一.ELF的部分结构定义 elf header(定义在/usr/include/elf.h)//64位的系统ELF文件头包括以下两个部分 #define EI_NIDENT (16) typedef ...

  7. 20135328信息安全系统设计基础第二周学习总结(vim、gcc、gdb)

    第三周学习笔记 学习计时:共8小时 读书:1 代码:5 作业:1 博客:7 一.学习目标 熟悉Linux系统下的开发环境 熟悉vi的基本操作 熟悉gcc编译器的基本原理 熟练使用gcc编译器的常用选项 ...

  8. iOS—— static和const联合使用;使用static const 与 #define

    static和const联合使用:   static将一个全局变量变成局部变量   const将一个局部变量变成局部常量 // 定义了一个局部常量      static const CGFloat ...

  9. Scrum敏捷精要

    本文抽取Scrum中的一些重要思想和概念,对Scrum敏捷执行的主题流程进行精要的介绍. 一.基本思想 个体和互动   高于   流程和工具 工作的软件   高于   详尽的文档 客户合作      ...

  10. 【MPI学习6】MPI并行程序设计模式:具有不连续数据发送的MPI程序设计

    基于都志辉老师<MPI并行程序设计模式>第14章内容. 前面接触到的MPI发送的数据类型都是连续型的数据.非连续类型的数据,MPI也可以发送,但是需要预先处理,大概有两类方法: (1)用户 ...