Heng30的博客
搜索 分类 关于 订阅

Linux驱动如何在proc目录创建文件?

2025-03-04

proc文件系统并不是真正存在于磁盘上的文件系统,而是由 Linux 内核动态创建的,用于提供一种访问内核数据结构和运行时系统信息的接口。它通常挂载在/proc目录下。一般用于:系统信息查看进程信息获取内核参数调整。所以我们可以通过proc文件系统向用户层提供驱动信息和内核信息。

实例代码

// simple.c

#include <linux/init.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/proc_fs.h>

#define BUFFER_SIZE 1024

static char buffer[BUFFER_SIZE];
static struct proc_dir_entry *proc_folder = NULL;
static struct proc_dir_entry *proc_file = NULL;

static int _open(struct inode *inode, struct file *file) {
    pr_info("simple_open\n");
    return 0;
}

static ssize_t _read(struct file *file, char __user *userbuf, size_t size,
                     loff_t *offset) {
    pr_info("simple_read\n");

    size = min(size, BUFFER_SIZE);
    unsigned long remain_len = copy_to_user(userbuf, buffer, size);

    if (remain_len > 0) {
        pr_err("copy_to_user failed\n");
        return -EIO;
    }

    return size;
}

static ssize_t _write(struct file *file, const char __user *userbuf,
                      size_t size, loff_t *offset) {
    pr_info("simple_write\n");

    size = min(size, BUFFER_SIZE);
    unsigned long remain_len = copy_from_user(buffer, userbuf, size);

    if (remain_len > 0) {
        pr_err("copy_from_user failed\n");
        return -EIO;
    }

    return size;
}

static int _release(struct inode *inode, struct file *file) {
    pr_info("simple_release\n");
    return 0;
}

static struct proc_ops fops = {
    .proc_open = _open,
    .proc_read = _read,
    .proc_write = _write,
    .proc_release = _release,
};

static int __init simple_init(void) {
    pr_info("simple_init\n");

    proc_folder = proc_mkdir("hello", NULL);
    if (!proc_folder) {
        pr_err("proc_mkdir hello folder failed\n");
        return -ENOMEM;
    }

    proc_file = proc_create("dummy", 0666, proc_folder, &fops);
    if (!proc_file) {
        pr_err("proc_create dummy file failed\n");
        proc_remove(proc_folder);
        return -ENOMEM;
    }

    return 0;
}

static void __exit simple_exit(void) {
    pr_info("simple_exit\n");
    proc_remove(proc_file);
    proc_remove(proc_folder);
}

module_init(simple_init);
module_exit(simple_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");

Makefile编译脚本

#!/bin/sh

top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build

obj-m += simple.o

all:
        make -C $(kernel-dir) modules M=$(top-dir)

clean:
        rm -f *.o *.ko *.mod *.mod.c *.order *.symvers
        make -C $(kernel-dir) clean m=$(top-dir)

测试

  • 安装驱动:insmod simple.ko

  • 移除驱动:rmmod simple.ko

  • 查看文件属性:ls /proc/hello/dummy -al

-rw-rw-rw- 1 root root 0 Mar  4 16:57 /proc/hello/dummy
  • 写入内容:echo "hello" > /proc/hello/dummy

  • 读取内容:cat /proc/hello/dummy | head -n 3

hello
hello
hello