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

内核模块中获取当前日期时间:ktime_get_real_ts64使用求助

键盘按键追踪器中ktime_get_real_ts64的实现方案

为什么用ktime_get_real_ts64

getnstimeofday因32位架构下time_t的2038年溢出问题被内核弃用,ktime_get_real_ts64是官方替代方案——它基于64位时间结构struct timespec64存储时间,彻底解决了年份溢出问题,且用法和旧函数高度相似。

核心实现思路

  1. 在键盘事件处理逻辑中调用ktime_get_real_ts64,传入struct timespec64指针获取当前实时时间戳
  2. 结合按键事件的类型、代码(如KEY_A对应29),将按键信息与时间戳绑定记录
  3. 可选择将记录输出到内核日志、写入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");

使用说明

  1. 编译模块:创建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文件

  1. 加载模块:使用root权限执行insmod key_tracker.ko

  2. 查看记录:执行dmesg -w实时监控内核日志,按下键盘按键即可看到带时间戳的按键记录

  3. 卸载模块:执行rmmod key_tracker

扩展建议

  • 如果需要将记录持久化或传递给用户态程序,可替换printk为proc文件读写、netlink通信或字符设备驱动逻辑
  • 若需转换为可读的日期时间格式,可在内核中调用time64_to_tm函数解析tv_sec字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:25:57