在Linux中,procfs是进程文件系统 (file system) 的缩写,包含一个伪文件系统(启动时动态生成的文件系统),可用于内核层和用户层交互信息。这个文件系统通常被挂载到 /proc 目录。由于 /proc 不是一个真正的文件系统,它也就不占用存储空间,只是占用有限的内存。故procfs是Linux驱动开发中很重要的debug手段。
1.procfs创建
proc节点可通过函数proc_create来创建,函数原型为:
#include <linux/proc_fs.h>
struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
参数proc_ops中可以挂载自己的读写函数,来实现数据交互:
static const struct proc_ops proc_ops = {
.proc_read = proc_read,
.proc_write = proc_write,
};
需要注意的是通过proc_create创建的节点是在/proc下,如果还想创建子目录需要用proc_mkdir来创建子目录:
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
2.procfs删除
proc节点可通过函数remove_proc_entry来删除:
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
3.示例代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#define PROCFS_NAME "procfs"
static ssize_t proc_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
int len = 6, ret;
static int flag = 0;
ret = copy_to_user(buf, "hello\n", len);
if (flag)
{
len = 0;
}
flag = !flag;
pr_err("<%s:%d> %d %d\n", __func__, __LINE__, flag, len);
return len;
}
static ssize_t proc_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
int ret;
char tmp_buf[64] = {0};
ret = copy_from_user(tmp_buf, buf, len);
if (ret) {
return -EFAULT;
}
pr_err("<%s:%d> %s\n", __func__, __LINE__, tmp_buf);
return len;
}
static const struct proc_ops proc_ops = {
.proc_read = proc_read,
.proc_write = proc_write,
};
int __init procfs_init(void)
{
int ret = 0;
if (proc_create(PROCFS_NAME, 0666, NULL, &proc_ops) == NULL) {
ret = -1;
printk("create /proc/%s failed.\n", PROCFS_NAME);
} else {
printk("create /proc/%s sucess.\n", PROCFS_NAME);
}
return 0;
}
void __exit procfs_exit(void)
{
remove_proc_entry(PROCFS_NAME, NULL);
printk("Remove /proc/%s sucess.\n", PROCFS_NAME);
}
MODULE_LICENSE("GPL");
module_init(procfs_init);
module_exit(procfs_exit);