事件监听器的实现——汇编与高级语言

Implementation of event listener - assembly vs high level language

程序集:

请考虑 Intel 8080. To handle an interrupt (for example from the keyboard), you simply have the keyboard pull the 'INT' pin high and place a 'vector' on the databus. The vector points to the location of the interrupt service routine (ISR) in the assembly program code. See this answer 了解更多详情。

高级语言:

考虑附加事件侦听器的概念。例如考虑 Javascript's keydown event listener. An example:

document.getElementById("demo").addEventListener("keydown", myFunction);

function myFunction() {
    document.getElementById("demo").style.backgroundColor = "red";
}

当 'demo' 元素处于焦点时按下某个键,将调用 myFunction

关系:

附加事件侦听器的概念与在程序集中具有 ISR 的概念有何关系?

我假设直接响应键盘中断的函数是 1) OS 内核的一部分和 2) 用 C 编写的。(这些假设是否正确?)

用户程序如何告诉这个 OS 中断处理程序在中断时提醒它? OS 函数在处理中断时是否保留一个可变大小的函数列表以供回调?那么 addEventListener 是否将用户回调函数附加到 OS 函数的列表中?

注意:我特别选择 Intel 8080 作为示例,因为与现代 CPU 相比,它没有辅助 OS 相关功能的奇特功能。

从按下一个键到 JavaScript keydown 事件侦听器中的代码成为 运行,这是一段漫长而复杂的旅程。假设一个 USB 键盘,通过硬件和软件层的路径是这样的:

  • 键盘(硬件层)
  • USB控制器(硬件层)
  • USB控制器驱动(内核层)
  • USB通用驱动(内核层)
  • HID 通用驱动程序(内核层)
  • HID键盘驱动(内核层)
  • OSUI事件处理(kernel/user层)
  • 浏览器UI事件循环(用户层)
  • 浏览器UI事件处理器(用户层)
  • JavaScript引擎事件处理器(用户层)
  • keydown事件监听器(用户层)

其中的大部分内容并不像您假设的那样有效。特别是没有键盘中断。相反,有一个 USB 中断,但它并不像您想象的那样工作。当您按下 USB 键盘上的某个键时,不会将消息发送到计算机并生成中断。相反,键盘将按键添加到其内部队列并等待计算机对其进行轮询。

这是因为USB通信完全由USB主机(电脑)调度。除非响应主机的请求,否则 USB 设备不允许在总线上通信。由于 USB 事务被安排在一毫秒的帧中,通常操作系统只会每毫秒轮询一次 USB 键盘,要求它报告自上次轮询设备以来发生的任何事件。只有当键盘响应这个请求时(或者可能当帧中所有预定的传输都完成时),USB 控制器才会产生中断。

键盘的响应将以 HID (Human Interface Device) 报告的形式出现。 HID 堆栈将对其进行解码以查看报告了哪些键盘事件,并将它们转换为所有键盘类型通用的格式。这将由操作系统中的某种用户界面层进一步处理(例如,Windows 上的 "Win32" API 层,或 Linux 上的 X 服务器)然后放入浏览器的 UI 事件队列。

浏览器不会因为按键被按下而"interrupted"。相反,浏览器将有一个主要的 UI 界面事件循环,并且事件只会在程序中的单个定义点一次处理一个。这个循环所做的就是从 UI 事件队列中提取事件并将它们分派到浏览器中的适当代码。当队列为空时(通常几乎所有时间),循环只是等待一个事件。在等待期间,事件循环的线程未由 OS 调度,并且未 运行 任何 CPU.

一旦 UI 事件循环获得键盘事件,它就会传递到浏览器的键盘事件处理程序,然后将其传递给 JavaScript 引擎。然后引擎将执行指定为 keydown 事件侦听器的函数。引擎可能有自己的事件队列,因为 JavaScript 事件通常也一次只处理一个。

None 除了内核中的一小部分代码在调用实际调度它们的 C 代码之前充当中断和系统调用的着陆点外,其中的

None 将用汇编语言编写。