IO是什么?
I/O 是 Input/Output 的缩写,即输入/输出。在计算机中,I/O 是指计算机与外部设备之间的数据传输和交换。计算机通过输入设备(如键盘、鼠标等)接收输入信号,通过输出设备(如显示器、打印机等)输出处理结果。
I/O 操作是计算机系统中的一种基本操作,包括读取和写入数据。计算机通过 I/O 操作与外部设备进行通信,可以让计算机系统与外部世界进行交互。例如,当我们在计算机上打开一个文件时,计算机需要从硬盘上读取文件的数据并将其显示在屏幕上,这就是一个典型的 I/O 操作。
I/O 操作的速度通常比计算速度慢得多,因此 I/O 操作的优化是计算机系统中的重要问题之一。
IO的分类
IO的分类 通常用户进程中的一个完整IO分为两阶段:用户进程空间-->内核空间、内核空间- ->设备空间(磁盘、网络等)。IO有内存IO、 网络IO和磁盘IO三种,通常我们说的IO指的是后两者。
I/O按照设备来分的话,分为两种:一种是网络I/O,也就是通过网络进行数据的拉取和输出。一种是磁盘I/O,主要是对磁盘进行读写工作。
用户态和内核态
用户态和内核态是指计算机系统中不同的运行级别。操作系统和应用程序运行在不同的运行级别,操作系统运行在更高的内核态(Kernel Mode),而应用程序则运行在更低的用户态(User Mode)。下面是它们的一些区别:
-
特权级别:内核态比用户态拥有更高的特权级别,可以执行更多的指令和访问更多的硬件资源。在内核态中,操作系统可以执行任何指令,包括直接访问硬件设备、修改内存映射等操作。
-
系统调用:应用程序如果需要进行一些特权级别较高的操作,需要通过系统调用(System Call)来请求操作系统完成。系统调用会触发一个从用户态到内核态的转换,这个转换会带来一定的开销。
-
调度:操作系统在内核态下进行进程调度和资源管理,而在用户态下则不会进行这些操作。当系统发生进程切换时,会从用户态切换到内核态,然后再切换到下一个进程的用户态。
-
安全性:内核态的代码拥有更高的特权,因此需要更加谨慎和安全地编写,以避免出现安全漏洞。
网络传输的两个阶段
在网络传输中,通常有两个阶段,它们分别是:
- 连接建立阶段:在这个阶段,客户端和服务器之间会进行一些握手操作,以确保双方能够正确地进行通信。这个阶段的主要目的是建立一个可靠的数据传输通道,包括以下步骤:
- 客户端向服务器发送一个连接请求;
- 服务器接收到连接请求后,向客户端发送一个确认信息;
- 客户端接收到确认信息后,再向服务器发送一个确认信息;
- 服务器接收到客户端的确认信息后,连接建立成功。
- 数据传输阶段:在连接建立成功后,客户端和服务器之间就可以开始进行数据传输。这个阶段的主要目的是通过建立的连接,在客户端和服务器之间传输数据,包括以下步骤:
- 客户端向服务器发送数据;
- 服务器接收到数据后进行处理,并向客户端发送响应数据;
- 客户端接收到响应数据后进行处理,并可能再次向服务器发送数据。
在数据传输阶段,还有一个重要的概念是流量控制,这是指在数据传输过程中,控制数据的发送速率,以避免数据包的丢失、延迟和堵塞等问题。流量控制通常通过调整发送和接收数据的速率来实现。
IO模型分类
5种IO模型分别是:阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型和异步IO模型。
- 阻塞式 I/O (Blocking I/O):应用程序会一直等待数据到来,直到读取或者写入完成后才会继续执行下一步操作。这种方式需要等待 I/O 操作完成才能继续,因此会造成较大的延迟,但是代码简单易懂。
- 非阻塞式 I/O (Non-blocking I/O):应用程序在发起 I/O 操作后,可以立即返回,而不必等待操作完成。应用程序可以不断地轮询 I/O 的状态,以判断操作是否完成,从而实现并发操作。但是轮询会占用 CPU 时间,造成资源浪费。

-
I/O 多路复用 (I/O Multiplexing):应用程序通过一个线程来同时监控多个 I/O 操作的状态,以决定哪些 I/O 操作已经完成,可以读取或写入数据。这种方式可以避免轮询带来的 CPU 资源浪费,但是需要额外的系统调用。
-
信号驱动式 I/O (Signal-driven I/O):应用程序通过向内核注册一个信号处理函数,当 I/O 操作完成时,内核会向应用程序发送一个信号。这种方式避免了轮询和阻塞,但是信号处理函数需要在所有线程中共享,因此会增加代码复杂度。
-
异步 I/O (Asynchronous I/O):应用程序在发起 I/O 操作后,可以立即返回,而不必等待操作完成。当 I/O 操作完成后,内核会通知应用程序,应用程序可以继续执行下一步操作。这种方式可以避免轮询和阻塞,但是需要操作系统和硬件的支持。

五种IO模型优缺点
下面是五种 I/O 模型的优缺点:
1. 阻塞式 I/O(Blocking I/O):
优点:
- 代码简单易懂,易于实现和调试。
- 对系统资源的占用较少。
缺点:
- 会造成较大的延迟,因为应用程序必须等待 I/O 操作完成后才能继续执行下一步操作。
- 不适用于多线程或多任务的应用程序,因为一个线程或任务的阻塞会影响其他线程或任务的执行。
2. 非阻塞式 I/O(Non-blocking I/O):
优点:
- 可以实现并发操作,应用程序可以不断轮询 I/O 的状态,以判断操作是否完成。
- 可以避免阻塞带来的延迟问题。
缺点:
- 轮询会占用 CPU 时间,造成资源浪费。
- 代码复杂度较高,需要进行错误处理和状态管理。
3. I/O 多路复用(I/O Multiplexing):
优点:
- 可以同时监控多个 I/O 操作的状态,避免了轮询带来的 CPU 资源浪费。
- 应用程序可以处理多个 I/O 操作,提高了系统的并发性能。
缺点:
- 实现较为复杂,需要进行错误处理和状态管理。
- 对于大量的连接,会造成多路复用器的性能瓶颈。
4. 信号驱动式 I/O(Signal-driven I/O):
优点:
- 可以避免轮询和阻塞,代码复杂度较低。
缺点:
- 信号处理函数需要在所有线程中共享,因此会增加代码复杂度。
- 对于大量的连接,会造成信号处理器的性能瓶颈。
5. 异步 I/O(Asynchronous I/O):
优点:
- 可以避免轮询和阻塞,代码复杂度较低。
- 可以实现真正的并行操作,多个 I/O 操作可以同时进行,提高了系统的并发性能。
缺点:
- 需要操作系统和硬件的支持。
- 对于小数据量的 I/O 操作,可能会造成额外的开销。
综上所述,不同的 I/O 模型各有优缺点,需要根据实际情况选择适合的模型。例如,对于大量的连接,可以使用 I/O 多路复用或异步 I/O,而对于少量的连接,可以使用阻塞式 I/O 或非阻塞式 I/O。
文章评论