1、数据传输过程
在 Linux 系统中,数据传输是通过 I/O 操作来实现的。I/O 操作是指数据从应用程序到内核,再到硬件设备(如磁盘、网络接口)的过程。
操作系统为了保护自己,设计了用户态、内核态两个状态。应用程序一般工作在用户态,当调用一些底层操作的时候(比如 IO 操作),就需要切换到内核态才可以进行。
服务器从网络接收的大致流程如下:
- 数据通过计算机网络传到网卡
- 把网卡的数据读取到socket缓冲区
- 把socket缓冲区读取到用户缓冲区,之后应用程序就可以使用
核心就是两次读取操作,五种网络
IO
模型的不同之处也就在于这两个读取操作怎么交互。
2、两组重要概念
阻塞(Blocking)与非阻塞(Non-Blocking)
1. 阻塞
-
定义:在阻塞模式下,当一个操作无法立即完成时,程序会被挂起,直到操作完成。这意味着在操作完成之前,程序会一直等待,不能继续执行其他任务。
-
特性:
- 等待:阻塞调用会使调用线程等待操作完成。
- 简单:编程模型较简单,易于理解和实现。
- 效率:在等待期间,线程无法做其他有用的工作,可能导致资源浪费。
-
例子:
- 文件读取:如果应用程序调用
read()
从文件中读取数据,但文件中没有数据,线程会阻塞,直到有数据可读。 - 网络请求:如果应用程序发起网络请求,线程会阻塞,直到收到响应。
- 文件读取:如果应用程序调用
2. 非阻塞
-
定义:在非阻塞模式下,当一个操作无法立即完成时,程序不会被挂起,而是立即返回。程序可以继续执行其他操作,并定期检查操作是否完成。
-
特性:
- 立即返回:非阻塞调用会立即返回,无论操作是否完成。
- 复杂:编程模型较复杂,需要轮询或回调机制来检查操作状态。
- 效率:可以在等待期间执行其他任务,利用 CPU 资源更高效。
-
例子:
- 文件读取:如果应用程序调用
read()
并且文件中没有数据,调用会立即返回,应用程序需要再次调用read()
以获取数据。 - 网络请求:在非阻塞网络编程中,程序发起请求后立即返回,程序通过轮询或事件机制来处理响应。
- 文件读取:如果应用程序调用