生命信号驱动

创建一个每秒钟自动递增一次的计数器,通过 /proc 或 sysfs 供用户读取

项目简介

在本章节中,我们将创建一个名为“生命信号”的Linux内核驱动。该驱动会每秒钟自动递增一个计数器,并通过 /proc 文件系统或 sysfs 向用户空间提供读取接口。这个项目是理解内核定时器、文件系统接口和内核模块编程的绝佳起点。

驱动功能

软件架构

用户空间 内核空间 读取 /proc/counter 生命信号驱动 内核定时器

关键数据结构

结构体 描述 用途
timer_list 内核定时器结构 用于实现每秒递增的定时器
proc_dir_entry /proc 文件入口 创建 /proc/counter 文件
file_operations 文件操作结构 定义文件的读写操作

代码实现

1. 驱动初始化

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>

#define DRIVER_NAME "heartbeat"
#define PROC_NAME "counter"

static unsigned long counter = 0;
static struct timer_list my_timer;
static struct proc_dir_entry *proc_entry;

static void timer_callback(struct timer_list *t)
{
    counter++;
    mod_timer(&my_timer, jiffies + HZ);
}

2. /proc 文件操作

static ssize_t proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    char str[20];
    int len;

    if (*ppos > 0)
        return 0;

    len = snprintf(str, sizeof(str), "%lu\n", counter);
    if (copy_to_user(buf, str, len))
        return -EFAULT;

    *ppos = len;
    return len;
}

static const struct proc_ops proc_fops = {
    .proc_read = proc_read,
};

3. 模块初始化和退出

static int __init heartbeat_init(void)
{
    // 初始化定时器
    timer_setup(&my_timer, timer_callback, 0);
    mod_timer(&my_timer, jiffies + HZ);

    // 创建 /proc 文件
    proc_entry = proc_create(PROC_NAME, 0444, NULL, &proc_fops);
    if (!proc_entry) {
        printk(KERN_ERR "Failed to create /proc/%s\n", PROC_NAME);
        return -ENOMEM;
    }

    printk(KERN_INFO "Heartbeat driver loaded\n");
    return 0;
}

static void __exit heartbeat_exit(void)
{
    del_timer(&my_timer);
    remove_proc_entry(PROC_NAME, NULL);
    printk(KERN_INFO "Heartbeat driver unloaded\n");
}

module_init(heartbeat_init);
module_exit(heartbeat_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple heartbeat driver");

编译和测试

  1. 编写 Makefile 文件
  2. 使用 make 命令编译驱动
  3. 使用 insmod heartbeat.ko 加载驱动
  4. 使用 cat /proc/counter 查看计数器值
  5. 观察计数器每秒自动递增

总结

通过本项目,我们实现了一个简单的“生命信号”驱动,掌握了以下核心技能:

这个驱动虽然简单,但包含了Linux驱动开发的基本要素,为后续更复杂的项目打下了坚实基础。