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(端口0x20)的ICW2需设置为
- 初始化完成后,通过读取主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
相关产品推荐
相关产品推荐

