diff --git a/docs/notes/01_c-basic/07_xdx/assets/7.png b/docs/notes/01_c-basic/07_xdx/assets/7.png new file mode 100644 index 0000000..a6c3c82 Binary files /dev/null and b/docs/notes/01_c-basic/07_xdx/assets/7.png differ diff --git a/docs/notes/01_c-basic/07_xdx/assets/8.png b/docs/notes/01_c-basic/07_xdx/assets/8.png new file mode 100644 index 0000000..857ff43 Binary files /dev/null and b/docs/notes/01_c-basic/07_xdx/assets/8.png differ diff --git a/docs/notes/01_c-basic/07_xdx/index.md b/docs/notes/01_c-basic/07_xdx/index.md index 5b78317..c558238 100644 --- a/docs/notes/01_c-basic/07_xdx/index.md +++ b/docs/notes/01_c-basic/07_xdx/index.md @@ -110,52 +110,54 @@ ### 1.3.1 如果存在缓冲区,键盘输入的数据是怎么到达程序的? * 当我们在键盘上输入数据并传递给程序时,通常会经历如下的几个步骤: - * ① `键盘输入数据`:当我们在键盘上按下某个键的时候,键盘会将这个动作转换为对应的电信号,传递给计算机。 - * ② `硬盘中断`:计算机的`键盘控制器`会检测到键盘按键输入,并通过`中断请求`通知 CPU。这个中断信号会暂停当前的程序执行,CPU进入中断处理状态(中断处理程序会接收这个中断信号,CPU 根据键盘输入触发的中断,调用操作系统内核中的中断处理程序)。 - * ③ `操作系统处理输入`:中断处理程序从键盘控制器获取输入的数据,并降低存储到内存的`缓冲区`(标准输入缓冲区)中。 - * ④ `缓冲区管理`:键盘输入的数据被存入`内存缓冲区`,操作系统会将这些数据暂时存放在缓冲区中,等待程序从缓冲区中读取数据。 - * ⑤ `程序读取数据`:程序通过系统调用或库函数,如:C 语言中的 scanf 函数从缓冲区中读取键盘输入的数据。并且,当程序调用读取输入的函数时,操作系统将缓冲区中的数据传递给程序。程序通过读取操作,将键盘输入的数据处理或输出到其他地方。 + * ① `键盘生成输入信号`:当我们在键盘上按下某个键的时候,键盘会将这个动作转换为对应的电信号,传递给键盘控制器。 + * ② `键盘控制器发送中断信号`:计算机的`键盘控制器`会检测到按键动作,向 CPU 发送中断请求。 + * ③ `CPU 执行中断处理程序`:CPU 暂停当前任务,进入中断处理状态,操作系统的中断处理程序接收并处理键盘输入。 + * ④ `操作系统将输入存入缓冲区`:键盘输入的数据被存入`内存缓冲区`,操作系统会将这些数据暂时存放在缓冲区中,等待程序从缓冲区中读取数据。 + * ⑤ `程序读取数据`:程序通过读取函数从缓冲区读取数据进行处理。 * 其对应的图示,如下所示: -```mermaid -sequenceDiagram - participant User as 用户 - participant Keyboard as 键盘 - participant Controller as 键盘控制器 - participant CPU as CPU - participant OS as 操作系统 - participant Program as 程序 +![](./assets/7.png) - User->>Keyboard: 按下按键 - Keyboard->>Controller: 生成输入信号 - Controller->>CPU: 发送中断请求 (IRQ) - CPU->>OS: 执行中断处理程序 (ISR) - OS->>OS: 处理输入并存储到缓冲区 (stdin) - Program->>OS: 通过系统调用读取缓冲区数据 - OS->>Program: 返回键盘输入数据 - -``` - - - - - - - -> [!NOTE] +> [!IMPORTANT] > > 其实,C 语言中的 `printf` 函数和 `scanf` 函数,其内部就使用了缓冲区。 > > * ① 当我们使用 `printf` 函数输出数据的时候,数据并不会立即就写出到输出设备(如:屏幕等)。而是先将其放置到 `stdout 缓冲区`中,然后在满足条件的时候,再从缓冲区中刷新到输出设备。 > * ② 当我们使用 `scanf` 函数输入数据的时候,数据并不会立即就从输入设备中读取(如:键盘等)。而是先将其放置到 `stdin 缓冲区`中,然后在满足条件的时候,再从缓冲区中加载数据。 - - ### 1.3.2 如果没有缓冲区,键盘输入的数据是怎么到达程序的? +* 当我们在键盘上输入数据并传递给程序时,通常会经历如下的几个步骤: + * ① `键盘生成输入信号`:当我们在键盘上按下某个键的时候,键盘会将这个动作转换为对应的电信号,传递给键盘控制器。 + * ② `键盘控制器发送中断信号`:键盘控制器检测到按键动作,向 CPU 发送`中断请求`,通知操作系统有输入数据。 + * ③ `操作系统处理输入`:操作系统接收到`中断信号`后,立即获取键盘数据并处理。由于没有缓冲区,操作系统必须将数据立即传递给程序。 + * ④ `程序直接读取数据`:程序必须在键盘每次输入后立即读取数据,并且处理这个输入,不会有任何数据被暂存或积累。 +> [!NOTE] +> +> 如果没有缓冲区,键盘输入的数据将无法有效地被程序管理和处理,系统的工作效率会显著下降,具体影响体现在以下几个方面: +> +> * ① `程序与设备的频繁交互`:在没有缓冲区的情况下,程序需要直接与键盘设备进行交互。这意味着每次按键输入,操作系统都必须立即将数据传递给程序处理。这样会带来以下问题: +> * **频繁的 I/O 操作**:每一次键盘输入都会触发一个 I/O 操作,将数据直接传输给程序。程序必须每次都立即响应输入设备,执行读操作,导致程序处理器频繁被中断。 +> * **实时响应要求**:程序需要时刻等待并响应输入,哪怕是输入非常小的数据(比如一个字符),程序都必须立即读取并处理。这对程序的设计提出了很高的实时性要求,可能会降低程序的运行效率。 +> * ② `处理效率低下`:由于没有缓冲区,程序无法积累多个输入数据再进行批量处理。每一次输入必须立即处理,程序执行的效率会受到影响: +> - **I/O 阻塞**:程序可能会因为等待输入设备的响应而阻塞。没有缓冲区的情况下,程序不能继续执行其他任务,必须等待每一次输入完成后才能继续执行其他操作。 +> - **浪费系统资源**:程序频繁地切换到处理I/O操作,导致处理器资源被大量占用。在处理较大数据量时,这种方式的效率极低,容易造成资源浪费。 +> * ③ `用户体验差`:从用户角度来看,程序对键盘输入的响应会显得非常僵硬,无法处理多个输入操作的积累: +> - **输入延迟**:程序必须实时处理每个键盘输入,用户输入数据的速度一旦超过程序的处理能力,可能导致输入延迟或丢失输入。 +> - **无法处理复杂输入**:如果用户需要输入多个字符或进行复杂的输入操作(比如连续输入多个命令),程序可能难以一次性正确处理,因为它只能逐一处理每一个输入,而无法一次性获取多个输入进行批量处理。 +* 其对应的图示,如下所示: +![](./assets/8.png) + +> [!IMPORTANT] +> +> 其实,C 语言中的 `printf` 函数和 `scanf` 函数,其内部就使用了缓冲区。 +> +> * ① 当我们使用 `printf` 函数输出数据的时候,数据并不会立即就写出到输出设备(如:屏幕等)。而是先将其放置到 `stdout 缓冲区`中,然后在满足条件的时候,再从缓冲区中刷新到输出设备。 +> * ② 当我们使用 `scanf` 函数输入数据的时候,数据并不会立即就从输入设备中读取(如:键盘等)。而是先将其放置到 `stdin 缓冲区`中,然后在满足条件的时候,再从缓冲区中加载数据。