角色介绍
- CPU: 计算核心,执行指令,处理中断。
- 键盘控制器 (Keyboard Controller): 一个专用芯片(如今多集成在 Southbridge/PCH 中),负责扫描键盘按键,生成扫描码(Scan Code)。
- 中断控制器 (如 APIC): 管理来自各种硬件的中断请求 (IRQ),决定其优先级并通知 CPU。
- 操作系统内核 (OS Kernel): 核心特权软件,管理硬件、内存、进程。
- 进程: 这里涉及两个:
- 终端进程/Shell 进程:运行着一个 Java 程序(如
java MyApp)。 - TTY/PTY 驱动和行规程(Line Discipline): 内核中管理终端输入输出的模块,负责处理退格、回车、缓冲等。
- 终端进程/Shell 进程:运行着一个 Java 程序(如
- Java 应用程序: 运行在 JVM 上的用户程序,等待从
System.in读取输入。
完整流程与技术细节
第一步:硬件中断 (Hardware Interrupt)
- 事件发生: 你按下键盘上的 'A' 键。
- 信号生成: 键盘控制器检测到按键,将其转换为一个扫描码(例如,
0x1E代表 'A' 按下),并通过中断请求线(IRQ1)向中断控制器发送一个电信号。 - 中断请求: 中断控制器接收信号,判断其优先级高于 CPU 当前执行的任务,于是向 CPU 发送一个中断信号。
- CPU 响应中断:
- 保存现场: CPU 完成当前正在执行的指令后,立即响应中断。它自动:
- 将当前的程序计数器(CS:EIP/RIP) 和标志寄存器(EFLAGS/RFLAGS) 压入当前线程的内核栈。这是硬件自动完成的。
- 清除某些标志位,自动从用户态切换到内核态。
- 查表跳转: CPU 根据中断号(IRQ1 对应一个特定的中断向量,例如 0x21)查询预先由操作系统设置好的中断描述符表(IDT),找到对应的中断服务例程(ISR) 的入口地址。对于键盘,这个 ISR 是内核中的
keyboard_interrupt()函数(或类似函数)。
- 保存现场: CPU 完成当前正在执行的指令后,立即响应中断。它自动:
第二步:内核中断处理 (Kernel ISR - 上半部)
- 执行 ISR (上半部):
- CPU 跳转到
keyboard_interrupt()函数(这是一段汇编和 C 混合的代码)。 - 软件保存现场: ISR 首先将可能会用到的通用寄存器(EAX, EBX 等)也压入当前线程的内核栈,确保用户态现场被完整保存。
- 读取数据: ISR 通过 IO 端口读取键盘控制器中的扫描码。
- 简单处理: 进行非常初步的处理,比如判断是按键按下还是释放,然后将扫描码转换为一个更通用的键码(Keycode)。
- 标记并退出: 由于 ISR 执行时要关闭中断,不能做太耗时的操作。它通常只是将数据放入一个缓冲区,并标记一个底半部(Bottom Half) 任务(如软中断、tasklet 等),然后迅速返回。返回前,它会向键盘控制器发送一个应答信号,告知中断已被处理,可以准备接收下一次按键。
- : ISR 从内核栈中弹出之前保存的通用寄存器。
- CPU 跳转到

