IO模型总结

博客详细介绍了同步IO和异步IO的概念,通过图解分析了同步阻塞、同步非阻塞、IO复用、信号驱动IO和异步IO五种模型的工作原理。重点对比了阻塞与非阻塞、同步与异步的区别,并指出只有异步IO在整个过程中不会阻塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POSIX对同步IO和异步IO的定义如下:

  •     同步IO操作(synchronous IO operation)   导致请求进程阻塞,直到IO操作完成。
  •     异步IO操作(asynchronous IO operation) 不导致请求进程阻塞。

单单理解两句话,我们可以看出同步IO就是阻塞的,异步IO就是非阻塞的。然而

同步阻塞,同步非阻塞,异步阻塞,异步非阻塞究竟要如何理解。

我们看图说话。

当我们在进程内调用一个读数据的操作如 String res = read();

阻塞IO :read方法内部先等待数据,再拷贝数据从内核到用户。该方法一直未返回,主进程一直阻塞。 即同步阻塞IO。

非阻塞IO:read方法不等待数据准备就绪就直接返回,返回的是一个错误码(EWOULDBLOCK),所以进程可以根据返回结果来决定下一步的走向,为了拿到数据,就只能如下一直循环。但当数据准备好了的话,read就会阻塞在拷贝数据上。   根据定义,只要阻塞进程就属于同步IO。所以该模型是同步非阻塞IO。     

 

String res= "";

while((res = read()) == EWOULDBLOCK){
   //返回错误码就一直循环
   
}

//处理res

IO复用于阻塞IO的唯一区别就是多了个select函数来选择就绪的描述符。所以他也是同步阻塞IO。对单个连接而言,因为IO复用要有两个系统调用,比之阻塞IO还有不如。但当连接成百上千时,IO复用使我们可以等待多个描述符。如下图所示,当有多个io时,select的存在避免了等待数据的CPU空转,因为随着描述符的增多,就绪的的描述符存在的可能性就越大。

 与IO复用密切相关的另一种IO模型是在多线程中使用阻塞IO,这样对整个服务器而言,也达到了有多个连接并处理就绪的连接的目的,但随着线程的数量增多,CPU进程(线程)切换的耗费是我们无法忍受的。

TOMCAT最新版本使用IO复用模型+多线程,即SELECT在一个线程,并为每一个就绪的连接开启一个线程来拷贝数据。可看TOMCAT如何处理连接。

 

信号驱动IO在拷贝阶段也要阻塞,他也是同步非阻塞IO。他与非阻塞IO模型的不同在于,不用调用者去一直(即我们的主线程)去轮询操作结果是否就绪。而是让内核就绪之后以SIGIO信号通知我们。我们得到通知就可以直接拷贝数据了。

 

异步IO与信号驱动IO非常类似,信号驱动IO是由内核通知我们合适可以启动一个IO操作,异步IO是由内核通知我们IO操作何时完成。根据定义,只有异步IO没有使主进程阻塞于IO调用。他是异步非阻塞IO。

总结,五种IO模型中,阻塞IO是阻塞的,其他都存在非阻塞的阶段,所以是非阻塞IO。

除了异步IO在任何阶段都不阻塞,其他模型都存在阻塞的阶段所以是同步IO。

 

 

关于异步阻塞的吐槽:我们上述没有一个符合异步阻塞。从理论上来说异步就不需要阻塞了,但从操作上来说,如果你使用异步IO,但在信号返回之前又不做其他事情,只等待IO完成,也算是逻辑层面的异步阻塞IO。我们所说的阻塞和非阻塞其实是由调用函数的返回时机决定的(直接返回还是等待),而若引入程序逻辑的概念(人为使程序等待等)其实是不应该的,这也是为什么看了那么多博客仍然晕的原因,尤其是那个茶壶烧水的例子,他虽然非常形象生动,但真的不如踏踏实实把所有IO模型过一遍理解的透彻,毕竟写代码的时候可不是用茶壶。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值