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

Linux环境下用C语言模拟方向键、回车等键盘事件的方法咨询

Linux C语言实现全局键盘事件模拟方案

Linux内核提供的uinput模块可以直接在用户态创建虚拟输入设备,完全满足你的需求,不需要引入Python依赖,实现逻辑如下:

1. 前置环境配置

树莓派官方Raspbian系统默认已内置uinput支持,按以下步骤配置权限即可:

  • 加载uinput内核模块:
    sudo modprobe uinput
  • 配置开机自动加载模块:将uinput写入/etc/modules-load.d/uinput.conf文件
  • 配置uinput设备访问权限:在/etc/udev/rules.d/99-uinput.rules中写入以下规则:
    KERNEL=="uinput", MODE="0660", GROUP="input", TAG+="uaccess"
  • 将当前运行程序的用户加入input组:
    sudo usermod -aG input $USER
    配置完成后重启系统生效,后续运行程序不需要root权限。

2. 核心C语言实现代码

#include <linux/uinput.h>
#include <linux/input-event-codes.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>

static int uinput_fd = -1;

// 初始化虚拟键盘设备
int init_virtual_keyboard(void) {
    struct uinput_setup dev_cfg;

    uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if (uinput_fd < 0) {
        perror("打开uinput设备失败");
        return -1;
    }

    // 启用按键事件类型
    ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);
    // 注册需要模拟的按键,可按需扩展
    ioctl(uinput_fd, UI_SET_KEYBIT, KEY_UP);
    ioctl(uinput_fd, UI_SET_KEYBIT, KEY_DOWN);
    ioctl(uinput_fd, UI_SET_KEYBIT, KEY_LEFT);
    ioctl(uinput_fd, UI_SET_KEYBIT, KEY_RIGHT);
    ioctl(uinput_fd, UI_SET_KEYBIT, KEY_ENTER);

    memset(&dev_cfg, 0, sizeof(dev_cfg));
    strncpy(dev_cfg.name, "iPod Clickwheel Virtual Keyboard", UINPUT_MAX_NAME_SIZE);
    dev_cfg.id.bustype = BUS_USB;
    dev_cfg.id.vendor = 0x1234;
    dev_cfg.id.product = 0x5678;

    if (ioctl(uinput_fd, UI_DEV_SETUP, &dev_cfg) < 0) {
        perror("配置uinput设备失败");
        close(uinput_fd);
        return -1;
    }

    if (ioctl(uinput_fd, UI_DEV_CREATE) < 0) {
        perror("创建uinput设备失败");
        close(uinput_fd);
        return -1;
    }

    return 0;
}

// 触发一次完整的按键动作(按下+弹起)
void trigger_key(int key_code) {
    struct input_event ev;

    // 发送按键按下事件
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = key_code;
    ev.value = 1;
    write(uinput_fd, &ev, sizeof(ev));

    // 发送同步事件,告知内核本次事件序列提交
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    write(uinput_fd, &ev, sizeof(ev));

    // 发送按键弹起事件
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = key_code;
    ev.value = 0;
    write(uinput_fd, &ev, sizeof(ev));

    // 再次发送同步事件
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    write(uinput_fd, &ev, sizeof(ev));
}

// 销毁虚拟设备,释放资源
void deinit_virtual_keyboard(void) {
    if (uinput_fd >= 0) {
        ioctl(uinput_fd, UI_DEV_DESTROY);
        close(uinput_fd);
        uinput_fd = -1;
    }
}

3. 对接现有逻辑

你现有代码中检测到iPod点击轮盘的操作触发时,直接调用trigger_key函数传入对应按键码即可:

  • 向上操作传KEY_UP
  • 向下操作传KEY_DOWN
  • 向左操作传KEY_LEFT
  • 向右操作传KEY_RIGHT
  • 确认点击传KEY_ENTER
    触发的事件为全局系统级事件,所有应用均可正常识别,和真实物理键盘触发的按键行为完全一致。

4. 编译与运行注意事项

  • 编译无需额外链接第三方库,直接用gcc编译即可:
    gcc your_source_code.c -o ipod_clickwheel_daemon
  • 如需模拟长按行为,只需间隔固定时间重复发送value为1的EV_KEY事件,最后发送value为0的弹起事件即可
  • 更多按键码定义可查看/usr/include/linux/input-event-codes.h头文件,按需添加需要模拟的按键即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:54:03