如何在Linux内核模块中模拟按键?编译keybdev.c遇函数未声明错误
在Linux内核模块中模拟按键操作(替代废弃的
handle_scancode) handle_scancode是老旧键盘驱动(如keybdev.c)的内部私有函数,早已被内核废弃,无法在外部模块中直接调用。现在模拟按键操作需要使用Linux输入子系统的标准公开接口,以下是具体实现步骤:
核心实现思路
通过注册一个虚拟input设备,调用输入子系统的API生成按键事件,内核会自动将这些事件分发到用户空间。
1. 注册虚拟Input设备
- 用
input_allocate_device()分配input设备结构体 - 标记设备支持的事件类型(必须包含
EV_KEY) - 标记设备支持的具体按键码(如
KEY_A、KEY_ENTER等) - 调用
input_register_device()完成注册
2. 模拟按键事件
完整的按键事件需要包含按下和释放两个动作,且每个动作后必须调用input_sync()同步事件,确保输入子系统正确处理:
- 按下按键:
input_report_key(dev, KEY_XXX, 1)+input_sync(dev) - 释放按键:
input_report_key(dev, KEY_XXX, 0)+input_sync(dev)
3. 示例代码
#include <linux/input.h> #include <linux/module.h> #include <linux/delay.h> static struct input_dev *virtual_key_dev; static int __init key_sim_init(void) { int ret; // 分配虚拟input设备 virtual_key_dev = input_allocate_device(); if (!virtual_key_dev) return -ENOMEM; // 设置设备名称(可选,便于识别) virtual_key_dev->name = "virtual-key-simulator"; // 标记支持按键事件 set_bit(EV_KEY, virtual_key_dev->evbit); // 标记支持的具体按键(可根据需求添加更多) set_bit(KEY_A, virtual_key_dev->keybit); set_bit(KEY_ENTER, virtual_key_dev->keybit); // 注册设备到输入子系统 ret = input_register_device(virtual_key_dev); if (ret) { input_free_device(virtual_key_dev); return ret; } // 模拟一次按键:按下A键 → 延迟100ms → 释放A键 input_report_key(virtual_key_dev, KEY_A, 1); input_sync(virtual_key_dev); msleep(100); input_report_key(virtual_key_dev, KEY_A, 0); input_sync(virtual_key_dev); return 0; } static void __exit key_sim_exit(void) { // 注销并释放设备资源 input_unregister_device(virtual_key_dev); input_free_device(virtual_key_dev); } module_init(key_sim_init); module_exit(key_sim_exit); MODULE_LICENSE("GPL");
4. 编译与加载
编写对应的Makefile:
obj-m += key_sim.o KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
执行make编译模块,再用insmod key_sim.ko加载,此时系统会收到模拟的按键事件。
内容的提问来源于stack exchange,提问作者JustOneMan
相关产品推荐
相关产品推荐

