procfs本身概述可以参考https://www.cnblogs.com/ck1020/p/7475729.html
1 procfs概述
procfs也是虚拟文件系统(debugfs、sysfs和procfs)之一。这个虚拟文件系统在内核空间和用户空间之间打开了一个通信窗口。在类Unix系统中体现了一种良好的抽象哲学,就是几乎所有的数据实体都被抽象成一个统一的接口--文件来看待,这样我们就可以用一些简单的基本工具完成大量复杂的操作。
procfs是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到一个目录树中,这样我们就可以简单直接的通过echo或cat这样的文件操作命令对系统信息进行查取和调整了。同时procfs也提供了一个接口,使得我们自己的内核模块或用户态程序可以通过procfs进行参数的传递。
对 /proc 进行读写(配置内核)
/# cat /proc/sys/net/ipv4/ip_forward
0
/# echo "1" > /proc/sys/net/ipv4/ip_forward
/# cat /proc/sys/net/ipv4/ip_forward
1
procfs的使用如同常规的文件系统一样,例如加载一个procfs (首先确定你的内核已经支持procfs默认如此):
# mount -t proc none /proc
也可以在/etc/fstab中加入如下一行使系统在启动时自动加载procfs(大多数系统中也是默认如此):
none /proc proc defaults 0 0
在proc文件系统中,主要包含三大类内容:进程相关部分、系统信息部分、子系统部分。
- 进程相关部分 (只读)
这部分文件都是以数字为名的子目录,这个数字就是相关进程的进程ID
- 内核信息部分 (只读)
这部分文件同样处于/proc的顶层目录,不过它们大部分都是常规、只读的文本文件,可以直接用cat查看信息。
- 内核各子系统相关部分 (部分可调)
这部分是系统内核参数调整的重头戏,在procfs中,除去上面所述的两部分内容外,还有很大一部分信息文件被存放在了一些并非以数字命名的特殊目录中,这些目录下的信息就是内核各个重要子系统的信息和可调参数,主要有:
bus 总线信息(只读)
drivers 驱动信息(只读)
fs 文件系统特别信息(只读)
ide IDE接口信息(只读)
irq IRQ信息(只读)
net 网络子系统信息(只读)
scsi SCSI系统信息(只读)
sysvipc IPC子系统信息(只读)
tty tty子系统信息(只读)
sys 系统内核可调参数 (可调)
作为Linux系统内核参数的抽象文件接口,Linux内核的大部分默认可调参数都被放在了 /proc/sys目录下,这些参数都以常规文件的形式体现,并且可以用echo/cat等文件操作命令进行调整,调整的效果是即时的
2 procfs编程
struct proc_dir_entry {
const char *name; // virtual file name
mode_t mode; // mode permissions
uid_t uid; // File's user id
gid_t gid; // File's group id
struct inode_operations *proc_iops; // Inode operations functions
struct file_operations *proc_fops; // File operations functions
struct proc_dir_entry *parent; // Parent directory
...
read_proc_t *read_proc; // /proc read function
write_proc_t *write_proc; // /proc write function
void *data; // Pointer to private data
atomic_t count; // use count
...
};
//创建目录
struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *);
//创建文件
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
const struct file_operations *proc_fops, void *data)
struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
int (*show)(struct seq_file *, void *), void *data)
说明:
proc_create_single_data 和 proc_create_data相比之下,proc_create_single_data 的参数是一个 show的函数指针
而proc_create_data的参数,是文件操作的结构体指针 file_operations *
例:
#例1
struct dentry *power;
int err = -ENOMEM;
power = debugfs_create_dir("power", NULL);
if (!power)
return err;
wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
S_IRUGO, power, NULL, &wakeup_sources_stats_fops);
#例2
static const struct file_operations proc_single_fops = {
.open = proc_single_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
int (*show)(struct seq_file *, void *), void *data)
{
struct proc_dir_entry *p;
p = proc_create_reg(name, mode, &parent, data);
if (!p)
return NULL;
p->proc_fops = &proc_single_fops; //使用了默认的fops,proc_single_fops
p->single_show = show; //初始化 single_show
return proc_register(parent, p);
}