当我们在 Windows 上按下一个键时会发生什么?

What happens when we press a key on Windows?

首先,我想告诉你,我是白手起家写这个问题的,因为我试图找到好的文档,但没有什么突出的...

按下按键会发生什么?

我觉得这很复杂,但我希望你能帮助我。

我搜索知道的:所有(但特别是主机上的程序启动以及密钥电信号如何编码和发送...)

可扩展主机控制器 (xHC) 具有定期传输环。 Windows 将此环编程为在每次以毫秒为单位的间隔过去时触发传输。正确的间隔在 USB 设备返回的 USB 描述符中指定。当传输发生时,xHC 将一个传输事件 TRB 放在事件环上并触发一个 MSI-X 中断,该中断作为某种处理器间中断绕过 IOAPIC。如果 Windows 检测到按下的键有一些变化,它将向当前具有焦点的应用程序发送一条消息(调用 window 的过程),其中一个参数中按下的键。

我不知道电信号,但我知道可扩展主机控制器是负责与现代 Windows 系统上的 USB 交互的 USB 控制器。由于现在 Windows 需要 x64 处理器,xHC 必须存在于您的主板上。 xHC 是符合 PCI-Express 规范的 PCI-Express 设备。

要找到 xHC,您:

  1. 在 RAM 中找到 RSDP ACPI table;

此 table 将在计算机启动期间由充当某种小型操作系统 (OS) 的 UEFI 固件找到。然后,OS 开发人员将编写一个名为 bootx64.efi 的小型 UEFI 应用程序,并将其放置在硬盘上的 FAT32 分区上。他们会将此应用程序放在 /boot/efi 目录中。 UEFI 固件将在计算机启动时直接启动该应用程序,这允许 OS 不需要用户输入来启动(类似于它过去与旧版 BIOS 的工作方式获取硬盘的第一个扇区并执行在那里找到的指令)。

UEFI 应用程序实际上是使用 EDK2 或 gnu-efi 编译的。这些编译器了解 UEFI 环境和规范。因此,他们将代码编译为系统调用,这些系统调用在引导期间存在并且可用于 OS 开发人员编写的 UEFI 应用程序。系统表(通常是 ACPI tables)作为参数提供给 UEFI 应用程序中的 UEFI 固件调用的“main”函数(通常称为 UefiMain)。因此,应用程序的代码可以简单地使用这些参数来查找 RSDP table 并将其传递给 OS.

  1. 使用 RSDP 查找 MCFG ACPI table;

table的链是RSDP -> XSDT -> MCFG。一旦 OS 找到了 MCFG,这个 table 指定了 PCI 配置的基地址 space。要与 PCI 设备交互,您可以使用内存映射 IO (MMIO)。您写入 RAM 中的某个位置,它会写入 PCI 设备的寄存器。因此,MCFG 指定了您将开始为插入计算机的不同 PCI 设备查找 MMIO 寄存器的基地址。

  1. 迭代 PCI 设备并查看它们的 ID,直到找到 xHC。

要迭代 PCI 设备,PCI 约定指定了一个公式,如下所示:

UINT64 physical_address = base_address + ((bus - first_bus) << 20 | device << 15 | function << 12);

base_address 用于特定细分组。每个段组可以有 256 个总线(suitable 用于大型服务器或具有大量组件的大型计算机)。最多可以有 65536 个段组,每个段组最多可以有 256 条 PCI 总线。每个 PCI 总线最多可以插入 32 个设备,每个设备最多可以有 8 个功能。每个功能也可以是一个 PCI 桥。这很容易理解,因为术语很清楚。这里的总线是 PCI 设备(如网卡、显卡、xHC、AHCI 等)用来与 RAM 通信的实际串行总线。该功能是 PCI 设备的一项功能,如控制 USB 设备、硬盘、HDMI 屏幕(用于显卡)等。PCI 桥将 PCI 总线桥接到另一条 PCI 总线。这意味着您可以拥有几乎无限数量的符合 PCI 规范的设备,因为桥允许通过添加其他 PCI 主机控制器来扩展设备树。

同时,总线只是一个介于 0 和 255 之间的数字。第一个总线在 MCFG ACPI table 中指定用于特定的段组。设备是0到31之间的数字,功能是0到7之间的数字。这个公式returns指向常规配置的物理地址space(所有功能都相同)它有特定的寄存器。这些寄存器用于确定设备的类型并为其加载适当的驱动程序。每个设备的每个功能因此得到一个配置 space.

对于 xHC,只有一个函数,其配置 space 返回的 ID 将为 class ID 的 0x0C 和 subclass ID 的 0x03 ( https://wiki.osdev.org/EXtensible_Host_Controller_Interface).

一旦找到 xHC,它就会变得相当复杂。您需要对其进行初始化并获取当前插入计算机的 USB 设备。您需要采取几个步骤才能使 xHC 正常运行。对于这一部分,我将让您阅读 xHCI 规范,该规范(在第 4 章)明确指定了需要采取的步骤 (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf)。

对于键盘部分,我将让您阅读我在计算机科学 stackexchange 上的回答之一:https://cs.stackexchange.com/questions/141870/when-are-a-controllers-registers-loaded-and-ready-to-inform-an-i-o-operation/141918#141918

一些不错的链接:

https://wiki.osdev.org/Universal_Serial_Bus

https://wiki.osdev.org/PCI