问题

计算机中,假设键盘同时按下两个键,会优先生效哪一个?

回答
在咱们日常用电脑的时候,有时候急了或者不小心,可能会同时按下两个键。这时候你可能会好奇,电脑到底会怎么处理?哪个键会“赢”呢?

这其实是个挺有意思的问题,因为电脑处理“同时发生”的事情,跟咱们直觉可能不太一样。它不是一个简单的“先到先得”,而是涉及到一些底层的东西。

首先,咱们得明白键盘是怎么跟电脑沟通的。

键盘不是直接跟CPU打交道的。它有一个叫做“键盘控制器”(Keyboard Controller)的东西。你按下键盘上的一个键,这个控制器就会捕捉到这个动作,然后生成一个叫做“扫描码”(Scan Code)的信号。这个扫描码就像是每个键的身份证号,每个键都有一个独一无二的数字代码。

接着,这个扫描码会被发送到主板上一个叫做“输入输出控制器”(I/O Controller)或者更现代一些的主板上的“芯片组”(Chipset)里。这些控制器负责把键盘的信号传递给CPU。

当两个键几乎同时被按下时,会发生什么?

关键就在于这个“几乎同时”是怎么发生的。键盘本身是有一定的处理能力的,它会扫描键盘上的按键矩阵。当你按下一个键时,它会在键盘的电路板上形成一个闭合的回路。

如果两个键是真的、在物理上完全同步按下的,那其实是极少发生的情况。更多时候,是你以为同时按了,但实际上可能有一个键比另一个早那么几十毫秒,或者说在键盘控制器检测到的时候,有一个信号稍微先一点点被发送出来。

就像你用录音机录下两个人同时说话,但其实仔细听,总有一个人的声音会先进入麦克风一点点。

所以,会优先生效哪一个?

通常情况下,不是哪个键“赢了”,而是哪个键的扫描码先被键盘控制器处理并发送到电脑系统中。

你可以想象成一个传送带。键盘控制器是传送带的起点,它每扫描一次键盘,就会看看有没有按键动作。如果它扫描到的那一刻,检测到了两个按键动作,它会按照它内部设定的顺序,把先被它捕捉到的那个按键的扫描码先放到待处理队列里。

这个队列就是“先到先得”的机制了。一旦扫描码被放入队列,它就会被一个接一个地发送给电脑。电脑接收到第一个扫描码,就处理第一个按键的事件。等到处理完第一个,再处理第二个。

影响因素有哪些?

1. 键盘本身的扫描速度和设计: 不同的键盘,它的控制器扫描按键的速度可能不一样。有些高端游戏键盘会更快速、更频繁地扫描按键,这样在几乎同时按下时,它更可能区分出哪个是先来的。
2. 物理按压的微小差异: 就算你感觉是同时的,人手的力量和按下速度总会有细微的差别。这个细微差别可能导致某个键的电路接触点比另一个先闭合,从而让键盘控制器先检测到。
3. 电脑处理器的响应速度和中断优先级(虽然这个影响非常小): 电脑收到键盘信号后,会产生一个中断请求(IRQ)。通常,键盘信号会有一个优先级,但这个优先级是在接收到信号之后才起作用的。所以,真正决定性的是扫描码的“发送”顺序。

举个例子:

假设你同时按下了“A”键和“S”键。

键盘控制器在扫描时,可能先检测到“A”键的回路闭合。
它立刻生成“A”键的扫描码,并发送出去。
然后,它又检测到“S”键的回路闭合,生成“S”键的扫描码,发送出去。

电脑接收到“A”的扫描码,就执行“输入 A”。接着接收到“S”的扫描码,就执行“输入 S”。所以你看到的,是先出现“A”,然后出现“S”。

有没有例外情况?

有时候,软件层面会做一些处理,比如防鬼键(Antighosting)和键位翻转(Key rollover)技术。这些技术主要是为了解决当你同时按下三个或以上按键时,某些组合的按键会失效的问题。

防鬼键: 主要是防止按下某些键组合时,系统把一个没按下的键也误判为按下了。
键位翻转(N键翻转,NKRO): 允许你同时按下任意数量的键,并且系统都能准确地识别和记录下来。如果你的键盘支持全键位翻转,那么它就能区分出你同时按下的所有键的顺序,而不是丢掉一些信号。

但是,即使有这些技术,底层的机制依然是“哪个扫描码先被处理”。这些技术只是让键盘控制器能处理更多、更复杂的按键组合,并以更精确的顺序传递信息。

总结一下,不存在哪个键“天生”就优先生效。 而是当你感觉同时按下两个键时,电脑操作系统收到的键盘信号的顺序决定了哪个键的动作会被先处理,然后才是第二个。这个顺序很大程度上取决于键盘控制器内部的扫描和数据发送机制,以及物理上极其微小的按键按下时间差。所以,与其说“优先生效”,不如说“先被电脑系统接收并处理”。

网友意见

user avatar

从几个层面上来解释一下吧,目前似乎没有太完整的回答。

首先,给一个链接:ti.com/lit/an/slaa514/s

这里有USB键盘的原理图和状态机,能从硬件层面上解释所有的问题。

首先,键盘其实就是一套开关矩阵(key matrix):

按键会接通相关的管脚,产生电信号。如果同时按下多个,就是多个信号。同时,手册上也描述了多个按键的情形,某些组合下,多个按键中的某几个会无法收到信号或者收到错误的信号("Ghost" Key):

所以,不管是按下一个,还是按下多个,对于芯片来说,都是可以处理的。

另外,键盘的键码叫做扫描码(Scan Code),扫描的意思已经很明显了,键盘控制器芯片是从周期性的扫描所有的管脚状态,对于高级的芯片,是一次性能处理多个按键的(比如我发的那个TI的),对于低级的芯片,可能就是一个一个的扫,扫到一个处理一个。所以如果是特别古老的键盘,同时按下几个键,在硬件上仍然是排队处理的。高级的芯片可以一次性获得所有的按键信息。

以TI这个芯片为例,它实际上支持多种模式,具体的扫描方式,手册中也给出了例子:

以上是硬件部分的设计。

再到传输层面上,PS/2和USB,这是两种不同的传输模式。

对于PS/2来说,使用的是键盘中断的方式,报告的是按下和弹起的事件。前面已经解释了,扫描码是从一个一个扫的,所以即使是同时按下,在扫描的过程中也是有先后次序的,按照这个次序报告键盘中断就可以了。

对于USB键盘就没有这种问题,USB键盘的报文格式是HID report,具体可以看这个回答:


HID report里只报告当前按下的按键信息,那么不管是同时按下几个键,都统一放到一个report里即可。所以USB键盘同时按下键位太多的时候,有些按键信息就丢失了。具体原因可以参见:

到了操作系统层面,比如Windows,实际上是针对硬件数据(HID report或者PS/2中断)再次重新解析。对于HID report,操作系统通常情况下就是从头开始读,所以哪个键码在report前面,哪个按键就被优先读取。

我在这个回答里,有描述Windows的处理方式(和调用栈):

复制部分内容出来(注意,调用栈比较老,不代表最新的Windows实现):

       1)硬件中断/硬件端口数据 2)键盘Port驱动(USB or PS/2) //Filter驱动在此 //KeyboardClassServiceCallback也在这一层被调用 3)kbdclass驱动 //处理键盘布局和键盘语言,部分高端的病毒也工作在这里 4)Windows内核边界(zwCreate/zwReadFile) ----------------------(系统调用)---------------------- 5)Windows内核边界(zwCreate/zwReadFile) 6)csrss.exe的win32k!RawInputThread读取,完成scancode和vk的转换 //SetWindowHook工作在这里(全局) //kbd_event工作在这里 7)csrss.exe调用DispatchMessage等函数分发消息(此处开始广播键盘消息) //SetWindowHook工作在这里(进程) //PostMessage和SendMessage在这里 8)各个进程(窗口线程)处理消息     

对于HID report或者PS/2中断信息来说,Windows的kbdclass驱动就会处理(重排),把按键转换成键盘布局指定的键码。Windows应用层是通过csrss.exe的win32k!RawInputThread来以Raw的方式读取按键的,这个时候都是一个一个读的。

这个问题下面有些使用脚本等方式模拟的,实际是在csrss这里实现的,包括Windows的VKEY的定义。

之后,再由csrss广播给各个窗口,这个时候已经是Windows的message格式的东西了。

如果能看得懂,最后放个结论

从根源的位置判断:

a) 对于PS/2类型的键盘,取决于键盘电路上扫描线路的布局,哪个按键的管脚靠前,哪个按键就会被优先扫到并上报;

b) 对于USB类型的键盘,取决于HID report上的次序,在前面的优先被处理,report上的次序可能源于扫描电路的次序,也可能是芯片有特殊控制

c) 操作系统会对键盘驱动获得的按键信息重新处理,实际应用层收到的内容不一定完全等价于总线信号的内容。

user avatar

反对一下其他人的回答。。。

其他人的回答都是说:哪怕你以为是同时,但计算机很快,能分辨出先后

但实际上,计算机说快很快,说慢也能很慢

这里的快慢指的是时钟周期

如果把时钟周期调成0.1Hz,也就是10秒一周期,那计算机应该算我们通常意义的“慢”


在一个时钟周期内,所做的所有操作(A-B-A先不考虑),计算机都认为是“同时”

比如以0为起始,在第2秒的时候的操作和第8秒的时候的操作,对计算机来说是同时;第9秒和第11秒不是同时


回到原题

“同时”按下两个键,比如第2秒按了a,第8秒按了b,同一时钟周期,哪个先生效?

不知道

“先后”按下两个键,比如第9秒按了a,第11秒按了b,不同时钟周期,哪个先生效?

a吗?也不知道


为嘛?

现在键盘按键的识别,很多是通过矩阵逐行扫描的方式工作的

比如一个键盘4行4列

会先看第0行哪些键按了,然后再扫第1行第2行第3行,再回到第0行

也就是说需要4个时钟周期,才能扫描完整个键盘

假如你同时(第2秒第8秒)按了两个键,这两个键又在同一行,被同时扫描到

对键盘来说,这一次扫描识别了两个键被按下,我会把这两个键的信息给cpu,至于把a放前面还是把b放前面,完全看写键盘芯片控制程序的程序员的处理方式

那先后按ab呢(第9秒按a,第11秒按b),假如a在第1行,b在第三行,此时扫描到了第2行,一个键也没有,下一个时钟周期扫第三行,那对键盘来说,是b先按了,然后下一轮发现a被按了

如果当时扫描在第0行,那下一个时钟周期,会先发现a被按下了,所以,哪怕你先按了a再按了b,都不能保证a先被生效

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有