【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, ®, &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");