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

QEMU平台UART驱动按下退格键收到delete字节而非backspace问题

问题原因

  • 终端默认字符映射:Unix-like系统的终端默认将backspace键映射为ASCII 127(DEL字符),而非ASCII 8(BS字符),你通过-serial mon:stdio将宿主机的标准输入绑定到QEMU的UART串口,所以按下backspace时UART收到的是127。
  • 输入设备冲突:你在启动参数中额外添加了-device virtio-keyboard-device参数,该参数会额外注册一个virtio标准键盘设备,物理键盘的delete键输入会被路由到这个virtio键盘设备的输入队列,而非UART的输入缓冲区,你当前只读取UART的输入,自然无法捕获delete键的输入。

修复方案

1. 适配backspace的输入映射

两种方案可选,推荐第二种无需修改外部环境:
方案一:启动QEMU前在当前终端执行如下命令,将终端的erase字符改为BS:

stty erase ^H

方案二:直接修改驱动的按键处理逻辑,将收到的127映射为退格操作,代码示例:

while (1) {
    char c = read_char();
    if (c == 127 || c == 8) { // 同时兼容两种退格输入
        // 退格处理逻辑,比如删除光标前字符
        puts("HERE: backspace\n");
    } else if (c == 10 || c == 13) {
        putchar('\n');
    } else {
        putchar(c);
    }
}

2. 解决delete键无响应问题

两种方案可选,根据需求选择:
方案一:如果不需要独立的virtio键盘设备,直接删除启动参数中的-device virtio-keyboard-device,所有按键输入都会走UART流。此时delete键默认会发送\x1b[3~的三字节转义序列,新增转义序列解析逻辑即可识别delete操作,示例代码:

// 新增转义序列状态变量
static int esc_state = 0;
while (1) {
    char c = read_char();
    if (esc_state == 0 && c == 0x1b) { // 收到ESC开头
        esc_state = 1;
        continue;
    } else if (esc_state == 1 && c == '[') {
        esc_state = 2;
        continue;
    } else if (esc_state == 2 && c == '3') {
        esc_state = 3;
        continue;
    } else if (esc_state == 3 && c == '~') {
        esc_state = 0;
        puts("HERE: delete\n");
        continue;
    } else {
        esc_state = 0; // 不匹配的转义序列重置状态
    }
    // 原有按键处理逻辑
    if (c == 127 || c == 8) {
        puts("HERE: backspace\n");
    } else if (c == 10 || c == 13) {
        putchar('\n');
    } else {
        putchar(c);
    }
}

方案二:如果需要使用virtio键盘设备,补充实现virtio键盘的驱动,读取设备的输入事件队列,解析键盘扫描码后映射为对应的输入字符,再接入现有按键处理逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:36:08