Linux 的 proc 文件系统编程
proc文件系统对应用户空间/proc/目录中的各个内容。其中的各个文件可以用于查看有关硬件、进程的状态。在驱动程序方面,proc文件系统中的各个文件可以作为内核空间到用户空间的接口,它们既可以作为辅助的信息使用,也可以作为独立的驱动程序使用。
1 proc文件系统的编程接口
proc文件系统的节点常常提供的是读、写功能,分别用于显示信息和控制,也实现文件的其他操作。
头文件proc_fs.h定义创建proc文件系统的函数:
struct procdirentry createprocentry(const char name,
modet mode, struct procdir_entry *parent);
struct procdirentry proccreatedata(const char name, mode_t mode,
struct procdirentry *parent,
const struct fileoperations procfops, void data);
void removeprocentry(const char name, struct procdirentry parent);
proc_dir_entry结构用于表示proc文件系统中的一个节点,可以表示目录和常规文件。create_proc_entry()和proc_create_data()函数用于创建节点,remove_proc_entry()函数用于删除节点。
proc文件系统节点当中表示读、写操作的函数类型的定义如下所示:
typedef int (readproct)(char page, char *start, off_t off,
int count, int eof, void data);
typedef int (writeproct)(struct file file, const char __user buffer,
unsigned long count, void *data);
proc_dir_entry结构如下所示:
struct procdirentry {
unsigned int low_ino;
unsigned short namelen;
const char *name; // 表示这个节点的名字
mode_t mode;
nlink_t nlink;
uid_t uid; // 文件的用户id和组id
gid_t gid;
loff_t size;
const struct inodeoperations *prociops; // 表示索引节点的操作
const struct fileoperations *procfops; // 表示proc文件系统的文件操作
struct module *owner;
struct procdirentry next, parent, *subdir;
void *data;
readproct *read_proc; // 表示读的函数类型
writeproct *write_proc; // 表示写的函数类型
atomic_t count;
int pde_users;
spinlockt pdeunload_lock;
struct completion *pdeunloadcompletion;
struct listhead pdeopeners;
};
proc_dir_entry结构当中的mode、uid、gid几个结构对应文件系统的信息。read_proc和write_proc函数指针用于定义一个proc文件系统中文件的读和写。如果需要进一步定义文件操作,可以实现file_operations结构。
在实际应用过程中,proc文件系统的节点中常常使用的是读、写操作。可以支持对于文件的完整操作,但是并不常用。
提示:使用proc文件系统完全可以实现类似字符设备的驱动。但在通常的应用中,proc文件系统中的文件通常只用于提供驱动程序辅助的功能。
2 proc文件系统的实现
内核源代码fs/proc目录中的内容是核心的proc文件系统的实现,其中实现的内容主要包括inode.c、root.c、base.c、generic.c、array.c等文件,其他几个文件都是针对某个proc文件系统中节点的单独实现。
cmdline.c文件实现了proc/cmdline节点,其实现如下所示。
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int cmdlineprocshow(struct seq_file m, void v)
{
seqprintf(m, "%s\n", savedcommandline); // 读取系统的命令行savedcommand_line
return 0;
}
static int cmdlineprocopen(struct inode inode, struct file file)
{
return singleopen(file, cmdlineproc_show, NULL);
}
static const struct fileoperations cmdlineproc_fops = {
.open = cmdlineprocopen,
.read = seq_read, // 读取的文件操作
.llseek = seq_lseek, // 移动位置操作
.release = single_release,
};
static int _init proccmdline_init(void)
{
proccreate("cmdline", 0, NULL, &cmdlineproc_fops); // 设置一个节点
return 0;
}
moduleinit(proccmdline_init);
cmdline文件实现了file_operations,seq_read()和seq_read ()两个函数是顺序文件的函数。在文件打开的过程中,调用single_open()函数,并将cmdline_proc_show()函数设置为其中的回调函数。saved_command_line就是char*类型的字符串,用于保存系统的命令行参数,cmdline_proc_show()函数将其取出拼凑成字符串,作为读的结果返回。
版权声明: 本文为 InfoQ 作者【韩超】的原创文章。
原文链接:【http://xie.infoq.cn/article/dee28fa9fc18839918b57ff7d】。文章转载请联系作者。
评论