0%

IO模型

IO模型

在Linux(UNIX)操作系统中,共有五种IO模型,分别是:阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动IO模型以及异步IO模型。

  • 参看:io模型

在处理 IO 的时候,阻塞和非阻塞都是同步 IO。只有使用了特殊的 API 才是异步 IO。

同步/异步和阻塞/非阻塞

阻塞/非阻塞 与 同步/异步不能简单的从字面理解,提供一个从分布式系统角度的回答。

  1. 同步与异步. 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication).所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

  2. 阻塞与非阻塞
    阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态: 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

  3. 打一个通俗的比方

  • 老张爱喝茶,废话不说,煮开水。
  • 出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
    1. 老张把水壶放到火上,立等水开。(同步阻塞)老张觉得自己有点傻
    2. 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
    3. 老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~的噪音。老张把响水壶放到火上,立等水开。(异步阻塞)
    4. 老张觉得这样傻等意义不大,老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)老张觉得自己聪明了。

所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

总结

阻塞、非阻塞、多路IO复用,都是同步IO,异步必定是非阻塞的,所以不存在异步阻塞和异步非阻塞的说法。真正的异步IO需要CPU的深度参与。换句话说,只有用户线程在操作IO的时候根本不去考虑IO的执行全部都交给CPU去完成,而自己只等待一个完成信号的时候,才是真正的异步IO。所以,拉一个子线程去轮询、去死循环,或者使用select、poll、epool,都不是异步。

  • 异步就是异步

有许多io模型的相关文章主要涉及四个概念同步( synchronous).异步( asynchronous).阻塞(plocking)和non- blocking).有些文章将这四个作了两两组合,于是有了异步阳塞和异步非阳塞,可以很明确地说完全是是羍强之理解。无论是<Uⅸ网络编程>一书中所列的○io模式,还是POSIX标准都没有提这两个概念。异步就是异步!只有同步时才有阻塞和非阻塞之说。

  • 阻塞和非阻塞

非阻塞时,要区分场合范围.比如linux中说的非阻塞iO和Java的NIO1.0中的非阻塞I/O不是相同的概念。从最根本来说,阻塞就是进程“被”休息,CPU处理其它进程去了,非阻塞可以理解成将大的整片时间的阻塞分成N多的小的阻塞,所以进程不断地有机会 被”CPU光顾,理论上可以做点其它事,看上去 Linux非阻塞I/O 要比阻塞好,但CPU会很大机率因socket没数据而空转 虽然这个进程是爽了,但是从整个机器的效率来说,浪费更大了!Java NIO1.0中的非阻塞I/O中的 Selector select()函数还是阻塞的,所以不会有无谓的CPU浪费Java NIO1.0,与其说是非阻塞I/O, 还不如说是,多路复用I/O,更好让人理解!

  • 异步

异步可以说是I/O最理想的模型:CPU的原则是,有必要的时候才会参与,既不浪费,也不怠慢。理想中的异步I/O, Application无需等待socket数据(也正是因此进程而被”休息”).也无需 copy socket data,将由其它的同学(理想状态,不是CPU)负责将socket data copy到Appliation事先指定的内存后,通知一声Appliation(一般是回调函数)
copy socket data, Application是不用做了,但事情总是需要做,不管是谁做,CPU是否还是要花费精力去参与呢?可以用”内存映射”以及DMA等方式来达到“不用CPU去参与繁重的工作”的目的. “内存映射”是不用copy,而DMA是有其它芯片来代替CPU处理.

同步和异步针对应用程序来,关注的是程序中间的协作关系;阻塞与非阻塞更关注的是单个进程的执行状态。

坚持原创技术分享,您的支持将鼓励我继续创作!