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

ops/2025/3/16 16:53:08/

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.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean: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,
};
#endifstruct 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);}
#elseproc_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;}#endifprintk("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");

http://www.ppmy.cn/ops/166249.html

相关文章

C 语言进【进阶篇】之动态内存管理:从底层机制到实战优化

目录 &#x1f680;前言&#x1f31f;动态内存分配的必要性&#x1f914;动态内存分配函数深度剖析&#x1f4af;malloc函数&#xff1a;内存申请的主力军&#x1f4af;free函数&#xff1a;释放内存的“清道夫”&#x1f4af;calloc函数&#xff1a;初始化内存的利器&#x1f…

Ceph(1):分布式存储技术简介

1 分布式存储技术简介 1.1 分布式存储系统的特性 &#xff08;1&#xff09;可扩展 分布式存储系统可以扩展到几百台甚至几千台的集群规模&#xff0c;而且随着集群规模的增长&#xff0c;系统整体性能表现为线性增长。分布式存储的水平扩展有以下几个特性&#xff1a; 节点…

Centos固定IP配置

虚拟机安装 安装vmware 网盘链接 安装centos7.5 网盘链接 安装教程自行查找 固定IP配置 对安装好的VMware进行网络配置&#xff0c;方便虚拟机连接网络&#xff0c;本次设置建议选择NAT模式&#xff0c;需要宿主机的Windows和虚拟机的Linux能够进行网络连接&#xff0c;…

深度解读DeepSeek部署使用安全(48页PPT)(文末有下载方式)

深度解读DeepSeek&#xff1a;部署、使用与安全 详细资料请看本解读文章的最后内容。 引言 DeepSeek作为一款先进的人工智能模型&#xff0c;其部署、使用与安全性是用户最为关注的三大核心问题。本文将从本地化部署、使用方法与技巧、以及安全性三个方面&#xff0c;对Deep…

【.Net 9下使用Tensorflow.net---通过LSTM实现中文情感分析】

.Net 9下使用Tensorflow.net---通过LSTM实现中文情感分析 一、创建项目&#xff0c;并导入各依赖项1、创建.net9的控制台应用程序2、通过nuget&#xff0c;导入依赖项&#xff1a;TensorFlow.NETTensorFlow.KerasSciSharp.TensorFlow.Redist–如果使用GPU训练&#xff0c;请使用…

理解langchain langgraph 官方文档示例代码中的MemorySaver

以下是langchain v0.3官方示例代码 from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import START, MessagesState, StateGraph# 可以理解为&#xff1a;定义一个流程&#xff0c;这个流程中用到的数据类型是Messages。 <---定义一个有向图&…

Android 拍照开发——移动虚拟机摄像头

背景 最近几个月&#xff0c;承接了客户安卓拍照开发需求&#xff0c;由于开发所在区域不允许使用实体安卓设备&#xff0c;只能在安卓虚拟机上进行调试&#xff0c;在调试过程中涉及到反复拍照、移除&#xff0c;需要让虚拟机拍摄的图像有区别&#xff0c;默认情况下&#xf…

Halcon 和 opencv比有什么区别与优劣

Halcon 和 OpenCV 都是机器视觉领域的重要工具&#xff0c;但它们的设计目标、功能特点和适用场景有所不同。以下是两者的详细对比&#xff1a; 1. ​定位与目标用户 ​Halcon&#xff1a; ​定位&#xff1a;商业机器视觉软件&#xff0c;专注于工业应用。​目标用户&#xf…