proc文件系统是一个伪文件系统;最初的设计目的是提供内核和用户交互的平台,使用户可以动态的管理系统,同时获取系统的运行时的信息。在proc中主要的信息便是系统进程信息.
1. proc_dir_entry结构体介绍
在/proc目录下创建文件,必然会用到proc_dir_entry结构体,其定义如下:
struct proc_dir_entry { unsigned int low_ino; //目录项的inode索引节点号,唯一,proc_register_dynamic动态分配 unsigned short namelen; //name的长度 const char *name; //node节点的name mode_t mode; //节点的类型type和权限permissions nlink_t nlink; //节点的链接数,初始化如果mode includes S_IFDIR为2,否则为1 uid_t uid; //节点owns的uid、gid、size gid_t gid; loff_t size; const struct inode_operations *proc_iops; const struct file_operations *proc_fops; struct proc_dir_entry *next, *parent, *subdir; //兄弟、父亲、子文件指针,parent一般设置为NULL,为/proc void *data; read_proc_t *read_proc; //指向read_proc函数的指针 write_proc_t *write_proc; //指向write_proc函数的指针 atomic_t count; /* use count */ int pde_users; /* number of callers into module in progress */ spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ struct completion *pde_unload_completion; struct list_head pde_openers; /* who did ->open, but not ->release */ };
const struct inode_operations *proc_iops;
// 索引节点操作,描述了与 索引节点inode对象关联的方法 ,该结构的地址存放在inode结构体域变量i_op字段中,inode_operatons结构体定义在fs.h文件中
const struct file_operations *proc_fops;
//定义了文件系统操作proc时的结构体指针,包含有read、write等函数;
当proc系统定义了自己的file_operations( proc_file_operations)时需要定义自己的读写函数:
read_proc_t *read_proc;
write_proc_t *write_proc;
这两个函数提供了对proc文件进程操作的简单接口,通过其就可以就可以实现对一些功能简单的proc文件的读写操作,而不需要调用系统的file_operations结构(使用起来比较麻烦)。
proc文件自己的read、write函数原型定义如下:
typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data); typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);
参数含义:
buf:是从驱动层向应用层返回的数据区;当有用户读此/proc/xxx的文件时,由系统分配一页的缓存区,驱动使用read_proc此写入数据。
start: 表示写在此页的哪里,此用法复杂,如果是返回小量数据(不超过一页)赋值为NULL。
offset:与read用法一致,表示文件指针的偏移。
count:与read用法一致,表示要读多少个字节。
eof: 输出参数。
data:由驱动内部使用。
return: 返回值是可读到的字节数。
struct proc_dir_entry *next, *parent, *subdir; //兄弟、父亲、子文件指针,parent一般设置为NULL,为/proc,目录树如下图所示:
查看Proc_fs.h源码可以发现,在使用/proc文件系统前,需要先使其初始化:
void proc_root_init(void); //初始化proc文件系统,定义在root.c文件中,大概定义了如图几个信息:
int __init proc_init_inodecache(void)
//为proc_inode创建slab cache,这是proc文件系统的主要部分,通常需要快速创建或销毁。
int register_filesystem(struct file_system_type * fs)
//注册文件系统类型proc,这个过程是文件系统初始化的关键步骤
kern_mount_data(&proc_fs_type, &init_pid_ns) //proc文件系统的挂在信息
proc_net_init(); //初始化与网络相关的文件目录等信息
proc_mkdir("driver", NULL); //创建/proc目录下的子目录sysvipc、fs、driver、fs/nfsd、openprom、bus等
使用create_proc_entry()函数创建文件,函数定义如下:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { struct proc_dir_entry *ent; nlink_t nlink; if (S_ISDIR(mode)) { //判断是否为目录,目录链接=2 if ((mode & S_IALLUGO) == 0) //按位与,判断UGO是否有suid、sgid、rwx等权限,若没有,给它赋予RX权限 mode |= S_IRUGO | S_IXUGO; //按位或,S_IRUGO | S_IXUGO的结果再与mode按位或,结果赋值给mode nlink = 2; } else { if ((mode & S_IFMT) == 0) //判断是否为文件 mode |= S_IFREG; //不是文件,设置为普通文件 if ((mode & S_IALLUGO) == 0) mode |= S_IRUGO; //权限设为UGO可读 nlink = 1; //链接=1 } ent = __proc_create(&parent, name, mode, nlink); //创建文件或目录 if (ent) { if (proc_register(parent, ent) < 0) { //创建成功,注册,这块使用默认的proc_file_operations kfree(ent); //释放ent ent = NULL; } } return ent; }
参数:
name:为要创建的文件名
mode:为创建文件的权限
parent:为创建文件的父目录,一般设置为NULL即就是/proc
截取proc_register()函数中部分代码如下:
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) { ...... if (S_ISDIR(dp->mode)) { if (dp->proc_iops == NULL) { dp->proc_fops = &proc_dir_operations; dp->proc_iops = &proc_dir_inode_operations; } dir->nlink++; } else if (S_ISLNK(dp->mode)) { if (dp->proc_iops == NULL) dp->proc_iops = &proc_link_inode_operations; } else if (S_ISREG(dp->mode)) { if (dp->proc_fops == NULL) dp->proc_fops = &proc_file_operations; if (dp->proc_iops == NULL) dp->proc_iops = &proc_file_inode_operations; } ...... }
从中可以发现该函数中调用了proc自定义的proc_file_operations函数:
static const struct file_operations proc_file_operations = { .llseek = proc_file_lseek, .read = proc_file_read, .write = proc_file_write, };
因此在使用create_proc_entry函数创建文件时,就可以直接的使用proc自定义的文件操作的proc_read、proc_write函数,实现更简单。
继续查看Proc_fs.h文件发现create_proc_read_entry也可以创建文件,和create_proc_entry函数没有本质区别,只不过在定义时就指定了创建后的文件使用read_proc_t *read_proc,即使用proc自定义的文件操作函数,其定义如下:
static inline struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void * data) { struct proc_dir_entry *res=create_proc_entry(name,mode,base); if (res) { res->read_proc=read_proc; res->data=data; } return res; }
remove_proc_entry(const char *name, struct proc_dir_entry *parent);
删除创建的文件,
name为文件名;
parent指向上级目录,为NULL时,默认为/proc目录
本文出自 “划舞鱼” 博客,请务必保留此出处http://ty1992.blog.51cto.com/7098269/1703794
原文:http://ty1992.blog.51cto.com/7098269/1703794