事件侦听器的实现-汇编与高级语言

时间:2018-07-09 04:32:54

标签: events assembly operating-system interrupt

组装:

考虑Intel 8080。要处理中断(例如,通过键盘),只需将键盘将“ INT”引脚拉高,然后在数据总线上放置一个“向量”即可。向量指向汇编程序代码中中断服务程序(ISR)的位置。有关更多详细信息,请参见this answer

高级语言:

考虑附加事件侦听器的概念。例如,考虑Javascript's keydown event listenerexample

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

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

当“演示”元素处于焦点状态时按下键时,将调用myFunction

关系:

附加事件侦听器的概念与将ISR组装在一起的概念有什么关系?

我认为直接响应键盘中断的功能是1)OS内核的一部分和2)用C编写的(这些假设正确吗?)

用户程序如何告诉此OS中断处理程序在发生中断时发出警报? OS函数在处理中断时是否保留可变大小的函数列表以进行回调?然后addEventListener会将用户回调函数附加到OS函数的列表中吗?

注意:我选择Intel 8080作为示例,是因为与现代CPU相比,它不具备支持操作系统相关功能的功能。

1 个答案:

答案 0 :(得分:2)

从按下按键到运行JavaScript keydown事件监听器中的代码是一段漫长而复杂的过程。假设使用USB键盘,则通过硬件和软件层的路径如下所示:

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

大多数情况都不符合您的假设。特别是没有键盘中断。而是有一个USB中断,但它并不能像您想象的那样正常工作。当您按下USB键盘上的某个键时,不会导致消息发送到计算机并产生中断。相反,键盘会将按键添加到其内部队列中,并等待计算机对其进行轮询。

这是因为USB通信完全由USB主机(计算机)安排。除非响应主机的请求,否则USB设备不允许在总线上通话。由于将USB事务安排为一毫秒的帧,因此通常情况下,操作系统只会轮询一次USB键盘一次,要求操作系统报告自上次轮询设备以来发生的任何事件。只有在键盘响应此请求后(或者可能在框架中所有预定的传输完成后),USB控制器才会产生中断。

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

按下键不会导致浏览器“中断”。取而代之的是,浏览器将具有主UI界面事件循环,并且事件仅在程序中的单个定义点处一次被处理。此循环所做的全部工作就是从UI事件队列中提取事件,并将其分派到浏览器中的相应代码。当队列为空时(通常几乎所有时间都是空的),循环只是在等待事件。在等待期间,事件循环的线程不是由操作系统安排的,也不在任何CPU上运行。

一旦UI事件循环获得键盘事件,它将被传递到浏览器的键盘事件处理程序,然后将其传递给JavaScript引擎。然后,引擎将执行分配为keydown事件监听器的功能。该引擎可能有自己的事件队列,因为JavaScript事件通常一次也只能处理一次。

除了内核中的少量代码在调用实际分派它们的C代码之前充当中断和系统调用的着陆点之外,这些都不用汇编语言编写。