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
相关产品推荐
相关产品推荐

