当前位置: 首页 > news >正文

【linux驱动开发】创建proc文件系统中的目录和文件实现

1. proc_mkdir_data

说明: 用于在 /proc 文件系统中创建一个目录
函数原型
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, struct proc_dir_entry *parent, void *data);
参数
const char *name: 要创建的目录的名称。
umode_t mode : 目录的权限模式,例如 0755 表示所有者可读、可写、可执行,组用户和其他用户可读、可执行。
struct proc_dir_entry *parent : 父目录的 proc_dir_entry 结构指针。如果为 NULL,则在根目录 /proc 下创建目录。
void *data: 与目录关联的用户数据。这个数据可以通过 proc_dir_entry 结构中的 data 字段访问。
返回值
成功时,返回指向新创建的 proc_dir_entry 结构的指针。
失败时,返回 NULL。

2. proc_create_data

说明: 用于在 /proc 文件系统中创建一个文件
函数原型
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *fops, void *data);
参数
const char *name: 要创建的文件的名称。
umode_t mode: 文件的权限模式,例如 0644 表示所有者可读、可写,组用户和其他用户可读。
struct proc_dir_entry *parent: 父目录的 proc_dir_entry 结构指针。如果为 NULL,则在根目录 /proc 下创建文件。
const struct file_operations *fops: 文件操作结构指针,定义了文件的读取、写入等操作。
void *data: 与文件关联的用户数据。这个数据可以通过 proc_dir_entry 结构中的 data 字段访问。
返回值
成功时,返回指向新创建的 proc_dir_entry 结构的指针。
失败时,返回 NULL。

3. remove_proc_entry

说明: 用于从 /proc 文件系统中删除一个目录或文件。
函数原型
void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
参数
const char *name: 要删除的目录或文件的名称。
struct proc_dir_entry *parent: 父目录的 proc_dir_entry 结构指针。如果为 NULL,则在根目录 /proc 下删除条目。
返回值
该函数没有返回值。

4. PDE_DATA

获取proc_create_data传入的私有数据。

5.示例代码

Makefile:

obj-m += hello.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
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>


#define PROC_FIX_DIR "fix"

struct my_test
{
	int a;
	int b;
	int c;
	int d;
};

// 读取 proc 文件的函数
static int proc_example_read(struct seq_file *m, void *v)
{
	printk("%s: %d\n", __func__, __LINE__);
    return 0;
}

// 打开 proc 文件的函数
static int proc_example_open(struct inode *inode, struct file *file)
{
    return single_open(file, proc_example_read, PDE_DATA(inode));
}

// 写入 proc 文件的函数
static ssize_t proc_example_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    char kbuf[64];
    int ret;
	int value = 0;
	unsigned int reg = 0;
	int cmd = 0;

	struct my_test *proc_test = PDE_DATA(file_inode(file));


    if (count > 63)
        return -EINVAL;

    if (copy_from_user(kbuf, buf, count))
        return -EFAULT;

	if(sscanf(kbuf, "%d_0x%x_%d", &cmd, &reg, &value))
	{
		if(cmd == 1)
		{
			printk("write %d to register 0x%08x \n", value, reg);
		}

		if(cmd == 2)
		{
			printk("read %d from register 0x%08x \n", value, reg);
		}
	}



    return count;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
static const struct proc_ops proc_example_fops = {
        .proc_open           = proc_example_open,
        .proc_read           = seq_read,
        .proc_lseek          = seq_lseek,
        .proc_write          = proc_example_write,
        .proc_release        = single_release,
};
#else
static const struct file_operations proc_example_fops = {
        .open           = proc_example_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
		.write          = proc_example_write,
        .release        = single_release,
};
#endif

struct proc_dir_entry *proc_dir;
struct proc_dir_entry *proc_file;



static void proc_example_init(void)
{
	struct my_test *data = NULL;

	data = kmalloc(sizeof(*data), GFP_KERNEL);
    if (!data) {
		printk("kmalloc error\n");
		return;
    }

	data->a = 1;
	data->b = 2;
	data->c = 3;

	
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
	 /* create fix entry */
	proc_dir = proc_mkdir_data(PROC_FIX_DIR, 0755, NULL, NULL);
	if (!proc_dir) 
	{
		printk("Unable to initialize /proc/%s/\n", PROC_FIX_DIR);
		return;
	}

	// 创建 proc 文件
	proc_file = proc_create_data("value", 0644, proc_dir, &proc_example_fops, data);
	if (!proc_file) {
		remove_proc_entry(PROC_FIX_DIR, NULL);
	}
#else
	proc_dir = proc_mkdir(PROC_FIX_DIR, NULL);
	if (!proc_dir) 
	{
			printk("Unable to initialize /proc/%s/\n", PROC_FIX_DIR);
			return;
	}
	
	if (!create_proc_read_entry("value", 0644, proc_dir, &proc_example_fops, data)) 
	{
			printk("Unable to initialize /proc/%s/%s\n",PROC_FIX_DIR, "value");
			return;
	 }

#endif
	printk("Proc example module loaded\n");

	return;

}

static void __exit proc_example_exit(void)
{
    remove_proc_entry("value", proc_dir);
	remove_proc_entry(PROC_FIX_DIR, NULL);

    printk("Proc example module unloaded\n");
}

static int __init mod_init(void)
{
	proc_example_init();
	printk("hello init\n");
	return 0;
}

static void __exit mod_exit(void)
{
	proc_example_exit();
	printk("hello exit\n");
	return;
}


module_init(mod_init);
module_exit(mod_exit);


MODULE_LICENSE("GPL");


相关文章:

  • win10 win+shift+s 无法立即连续截图 第二次截图需要等很久
  • [RA-L 2023] Coco-LIC:基于非均匀 B 样条的连续时间紧密耦合 LiDAR-惯性-相机里程计
  • API自动化测试实战:Postman + Newman/Pytest的深度解析
  • 深度学习中学习率调整策略
  • java实现智能家居控制系统——入门版
  • vue3怎么和大模型交互?
  • spring security学习入门指引
  • Spring框架详解(IOC容器-上)
  • 【PyTorch教学】pytorch 基本语法
  • WebForms HTML:深入理解与高效运用
  • 并发编程面试题一
  • 《深入剖析:鸿蒙开发工具模拟器在人工智能应用模拟测试中的特性与局限》
  • 【CXX】6.8 Vec<T> — rust::Vec<T>
  • 房屋交易平台设计与实现(代码+数据库+LW)
  • ECA注意力机制改进思路
  • 第三章-PHP流程控制语句
  • Linux 运行级别
  • 带宽管理配置实验
  • 【Azure 架构师学习笔记】- Azure Databricks (21) --费用相关
  • 进程管理:前后台切换
  • 83岁山水花鸟画家、书法家吴静山离世,系岭南画派代表人物
  • 推开“房间”的门:一部“生命存在的舞台” 史
  • 上海这个咖啡文化节首次“走出去”,率本土品牌亮相英国伦敦
  • 时隔3年,持续近2小时,俄乌在土耳其谈成了什么?
  • 讲座|消逝之钟:《红楼梦》与《布登勃洛克一家》中的时间观
  • 新华时评:让医德医风建设为健康中国护航