轻松搞懂5种IO模型

同步阻塞IO、同步非阻塞IO、IO多路复用、异步阻塞IO、异步非阻塞IO,这五种IO模型有没有朋友记过多次了,但是总是记不住?那是因为没有理解本质。5年前我记住了,到现在发现记忆和区分仍然很清晰,今天把理解方法介绍给大家。

首先,大家先思考一个问题:

IO操作其实主要为了读和写。本文以读数据做说明。

当程序调用read方法时,会切换到系统内核来完成真正的读取。而读取又分为等待数据和复制数据两个阶段。如下图所示:

7d691728d734f6665923354d02ab44e5.png

同步阻塞IO

a185e2a05a48f121f663fb43d7a46a80.png

如上图所示,用户线程发起一个read请求,会切换到内核空间。这时候如果没有数据过来,则用户线程和对应的内核线程什么都做不了,一直等到有数据进来,并且完成了内核态的数据复制才继续返回用户空间继续执行。这整个过程是阻塞的。

同步非阻塞IO

896c76dad5458efd66e3aa4a8f3363ee.png

如上图所示,用户线程发起一个read请求,会切换到内核空间。这时候如果没有数据过来,则直接返回。它可以再次轮循发起read,如果某一次发现有数据过来,则等待完成了内核态的数据复制才继续返回用户空间继续执行。

这个过程中,没有数据时是非阻塞的。有数据时是阻塞的,被称为非阻塞IO。这种方式涉及多次内核切换,某些情况下反而会影响性能。之前业界发生过一个由阻塞切换成非阻塞,流量高峰时性能不足引起的重大故障。

IO多路复用

c668e59f0e92ef5b124d0ffe4df3567f.png

如上图所示,用户线程发起一个select请求,会切换到内核空间。这时候如果没有数据过来,则阻塞直到有数据时返回给用户线程。用户线程收到有数据的消息,发起read操作同步等待直到完成内核态的数据复制才继续返回用户空间继续执行。

这时候,是不是有朋友冒出来一个问题:似乎看不到多路复用的优势啊。似乎阻塞才是最佳选择啊。

上面都是以最简单的例子来介绍的,下面来看一个复杂一些的阻塞IO。

99b35f4dbc8c7af64e8151d35fdfba12.png

如上图所示,用户线程发起一个read请求,会切换到内核空间。这时候又有另外一个连接请求过来。这个线程不会立即影响这个连接请求,而是一直等到有数据进来,并且完成了内核态的数据复制才继续返回用户空间继续执行。处理完第一个连接的所有read操作之后,才会响应新的连接。新连接从accept(netty中建立连接的函数)到read都是同步阻塞的,每次只能处理一个连接的事件。

1c36ecdc77b77834486f87cfb5639fd9.png

如上图所示,多路复用时,用户程序发起一个select操作,会返回一批事件,有read、write、accept(netty中建立连接的事件)。这时候,该等的时间select操作都已经做了。这时候,用户线程可以用新的线程(worker线程)直接去建立连接、复制数据。

异步非阻塞IO

这里就要明确IO模型中,同步和异步的概念了。

同步:线程自己去获取结果。(一个线程)

异步:线程自己不去获取结果,而由其他线程送结果。(至少两个线程)

8180573a31a02baef296f381c0376f5e.png

如上图所示,异步是通过回调来完成的。用户程序发起read操作只是去通知操作系统我在等待数据。另外一个线程等待数据复制完成回调read方法返回结果。异步IO从实现上是基于操作系统信号驱动的,也叫信号驱动IO。

异步阻塞IO和异步非阻塞IO又有什么区别呢?看上面的过程,异步read操作去通知完操作系统肯定是直接返回的,也就是肯定是非阻塞的。其实根本没有异步阻塞这种说法,纯属误传。

总结

最近发现,为了把一件事情讲清楚,要写的字越来越多。因为写的过程中会引出一些额外层面的问题需要解释。两者没有分离好反而不好理解。

我就想出来现在的办法,先在一篇文章中阐述一件事,同时抛出来一个问题让大家思考。然后另起一篇把问题讲透。就像本周的《HTTP状态码1XX深入理解》《【答案公布】客户端与服务端通信时,所有的http状态码是否都是服务端返回的?》。自己觉得这种方式更加清晰,大家觉得如何呢?

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux IO 模型是指 Linux 操作系统中的 IO 处理机制。它的目的是解决多个程序同时使用 IO 设备时的资源竞争问题,以及提供一高效的 IO 处理方式。 Linux IO 模型主要分为三阻塞 IO非阻塞 IOIO 多路复用阻塞 IO 指的是当程序进行 IO 操作时,会被挂起直到 IO 操作完成,这方式简单易用,但是对于高并发环境不太适用。 非阻塞 IO 指的是程序进行 IO 操作时,如果无法立即完成,会立即返回一个错误码,程序可以通过循环不断地进行 IO 操作来实现轮询的效果。非阻塞 IO 可以提高程序的响应速度,但是会增加程序的复杂度。 IO 多路复用指的是程序可以同时监听多个 IO 设备,一旦有 IO 事件发生,就会立即执行相应的操作。IO 多路复用可以提高程序的效率,但是需要程序员手动编写代码来实现。 Linux IO 模型还有其他的实现方式,比如信号驱动 IO异步 IO 等。但是这些方式的使用比较复杂,一般不常用。 ### 回答2: Linux中的IO模型是指操作系统在处理输入输出的过程中所遵循的一方式。它主要包括阻塞IO非阻塞IO多路复用IO异步IO模型阻塞IO是最简单的IO模型,当一个IO操作发生时,应用程序会被阻塞,直到IO操作完成才能继续执行。这模型的特点是简单直接,但是当有多个IO操作时会造成线程的阻塞,影响系统的性能。 非阻塞IO是在阻塞IO的基础上发展而来的,应用程序在发起一个IO操作后可以继续执行其他任务,不必等待IO操作的完成。但是需要通过轮询来不断地检查IO操作是否完成,效率相对较低。 多路复用IO使用select、poll、epoll等系统调用来监听多个IO事件,当某个IO事件就绪时,应用程序才会进行读写操作,避免了前两模型的效率问题。多路复用IO模型适用于连接数较多时的场景,如服务器的网络通信。 异步IO是最高效的IO模型,应用程序发起一个IO操作后,立即可以执行其他任务,不需要等待IO操作的完成。当IO操作完成后,操作系统会通知应用程序进行后续处理。异步IO模型常用于高吞吐量、低延迟的应用,如高性能服务器和数据库等。 总之,Linux IO模型提供了多不同的方式来处理输入输出,每模型都有其适用的场景和特点。选择合适的IO模型可以提高系统的性能和效率。 ### 回答3: Linux IO模型是指操作系统中用于处理输入输出操作的一方法或机制。在Linux中,常见的IO模型阻塞IO非阻塞IOIO多路复用异步IO阻塞IO是最基本的IO模型,当应用程序发起一个IO请求时,它将一直阻塞等待直到IO操作完成,期间无法做其他任务。虽然简单易用,但是对资源的利用不高。 非阻塞IO在发起一个IO请求后,不会阻塞等待IO操作完成,而是立即返回并继续做其他任务。应用程序需要不断地轮询IO操作状态,直到操作完成。由于需要不断轮询,对CPU的占用较高,但可以提高资源的利用率。 IO多路复用是通过一个线程同时监听多个IO事件,从而实现并发处理多个IO操作。在IO多路复用模型中,应用程序不需要进行轮询,而是通过调用select、poll或epoll等系统调用监听多个文件描述符的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、付费专栏及课程。

余额充值