You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64自制OS键盘驱动无响应问题排查求助

问题分析与解决方案

从你的描述和代码来看,核心问题是键盘IRQ1中断从未触发,结合QEMU调试信息中没有INT=0x21(IRQ1对应的中断向量)的记录,以下是最可能的原因及验证/修复步骤:

1. 确认IRQ到中断向量的映射是否正确

x86架构中,PIC默认将IRQ0-7映射到IDT的0x20-0x27向量号,IRQ1对应的是0x21,而非直接使用IRQ编号1。

  • 检查register_interrupt_handler函数的实现:如果它直接把传入的IRQ1(即1)作为IDT向量索引,那实际注册的是CPU异常向量0x01(调试异常),而非键盘中断的0x21。
  • 修复方式:注册时需给IRQ号加上PIC偏移量0x20,即调用register_interrupt_handler(IRQ1 + 0x20, keyboard_callback),或者修改register_interrupt_handler内部自动处理这个偏移。

2. 验证PIC初始化是否正确

即使你确认IRQ1未被屏蔽,若PIC未完成初始化,键盘中断也无法正常发送到CPU:

  • 确保你已经发送了PIC初始化命令(ICW1-ICW4):
    • 主PIC(端口0x20)的ICW2需设置为0x20(指定IRQ0的向量起始为0x20);
    • 确认ICW4中设置了0x01(启用8086模式);
  • 初始化完成后,通过读取主PIC的屏蔽寄存器(0x21)确认IRQ1位是0(未被屏蔽):inb(0x21) & 0x02结果应为0。

3. 检查IDT中断门的配置

x86-64的IDT每个条目是16字节的中断门描述符,需确保register_interrupt_handler正确生成了合法的64位中断门:

  • 确认描述符的选择子是你代码段的选择子(调试信息中CS=0x08,正确);
  • 确认偏移量是keyboard_callback的完整64位地址;
  • 确认描述符的类型字段设置为中断门(0xE),DPL=0(内核级),且P位(存在位)置1;
  • 确保已经执行lidt指令加载IDT表到CPU。

4. 启用键盘控制器的中断

键盘默认可能未启用中断,需向键盘控制器发送命令开启:
在init_keyboard函数中添加以下代码:

// 等待键盘控制器输入缓冲区为空
while (inb(KEYBOARD_STATUS_PORT) & 0x02);
// 发送启用键盘中断的命令
outb(KEYBOARD_STATUS_PORT, 0xAE);
// 再次等待缓冲区为空,然后读取ACK(可选)
while (inb(KEYBOARD_STATUS_PORT) & 0x02);
inb(KEYBOARD_DATA_PORT);

5. 额外调试建议

  • 在QEMU中添加-d int参数,更详细地查看所有中断触发情况,确认是否有INT=0x21的记录;
  • 在register_interrupt_handler中添加调试输出(比如用print_char输出一个特定字符),确认函数确实被调用且注册到了正确的IDT向量;
  • 手动触发一个测试中断(比如通过PIC发送命令),验证IDT和中断处理链路是否正常。

内容的提问来源于stack exchange,提问作者AlexTheNewDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:23:13