内核模块中获取当前日期时间:ktime_get_real_ts64使用求助
键盘按键追踪器中ktime_get_real_ts64的实现方案
为什么用ktime_get_real_ts64
getnstimeofday因32位架构下time_t的2038年溢出问题被内核弃用,ktime_get_real_ts64是官方替代方案——它基于64位时间结构struct timespec64存储时间,彻底解决了年份溢出问题,且用法和旧函数高度相似。
核心实现思路
- 在键盘事件处理逻辑中调用
ktime_get_real_ts64,传入struct timespec64指针获取当前实时时间戳 - 结合按键事件的类型、代码(如KEY_A对应29),将按键信息与时间戳绑定记录
- 可选择将记录输出到内核日志、写入proc文件或通过IPC传递给用户态进程
可运行内核模块代码
以下是基于Linux input子系统的按键追踪实现,包含完整的时间戳获取逻辑:
#include <linux/module.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/ktime.h> // 处理input事件的回调函数 static int key_tracker_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct timespec64 ts; // 获取当前系统实时时间(64位,无2038问题) ktime_get_real_ts64(&ts); // 仅处理按键按下事件(value=1表示按下,0表示松开,2表示长按重复) if (type == EV_KEY && value == 1) { printk(KERN_INFO "Key [0x%x] pressed at: %lld.%09ld\n", code, (long long)ts.tv_sec, ts.tv_nsec); } return 0; } // 连接input设备时的回调 static int key_tracker_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { int ret = input_register_handle(&handler->h_list, dev, handler); if (ret) return ret; printk(KERN_INFO "Key tracker attached to device: %s\n", dev->name); return 0; } // 断开input设备时的回调 static void key_tracker_disconnect(struct input_handle *handle) { input_unregister_handle(handle); printk(KERN_INFO "Key tracker detached from device\n"); } // 匹配所有键盘类input设备 static const struct input_device_id key_tracker_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, .evbit = { BIT_MASK(EV_KEY) } }, { }, // 终止符 }; MODULE_DEVICE_TABLE(input, key_tracker_ids); // input处理器结构体定义 static struct input_handler key_tracker_handler = { .event = key_tracker_event, .connect = key_tracker_connect, .disconnect = key_tracker_disconnect, .name = "key_tracker", .id_table = key_tracker_ids, }; // 模块加载入口 static int __init key_tracker_init(void) { int ret = input_register_handler(&key_tracker_handler); if (ret) { printk(KERN_ERR "Failed to register input handler: %d\n", ret); return ret; } printk(KERN_INFO "Key tracker module loaded successfully\n"); return 0; } // 模块卸载入口 static void __exit key_tracker_exit(void) { input_unregister_handler(&key_tracker_handler); printk(KERN_INFO "Key tracker module unloaded\n"); } module_init(key_tracker_init); module_exit(key_tracker_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("64-bit timestamp enabled keyboard key tracker"); MODULE_VERSION("1.0");
使用说明
- 编译模块:创建Makefile文件
obj-m += key_tracker.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
执行make编译生成.ko文件
加载模块:使用root权限执行
insmod key_tracker.ko查看记录:执行
dmesg -w实时监控内核日志,按下键盘按键即可看到带时间戳的按键记录卸载模块:执行
rmmod key_tracker
扩展建议
- 如果需要将记录持久化或传递给用户态程序,可替换
printk为proc文件读写、netlink通信或字符设备驱动逻辑 - 若需转换为可读的日期时间格式,可在内核中调用
time64_to_tm函数解析tv_sec字段
内容的提问来源于stack exchange,提问作者Vikas Mishra
相关产品推荐
相关产品推荐

