/proc下文件系统初识

proc文件系统是一个伪文件系统;最初的设计目的是提供内核和用户交互的平台,使用户可以动态的管理系统,同时获取系统的运行时的信息。proc之所以被称为“伪”文件系统,是因为它只存在内存中,不像普通文件一样占用外存空间。在proc中主要的信息便是系统进程信息,进程的地址空间是动态改变的,所以应用程序在每次读取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: 输出参数,设置*eof=1会少触发一次读操作,否则会读三次。
data:由驱动内部使用。
return: 返回值是可读到的字节数。

struct proc_dir_entry *next, *parent, *subdir; //兄弟、父亲、子文件指针,parent一般设置为NULL,为/proc,目录树如下图所示:

  1. 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等3. 创建proc目录下的文件
使用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;
}
*

  1. 删除创建的文件

    remove_proc_entry(const char *name, struct proc_dir_entry *parent);
    删除创建的文件,
    name为文件名;
    parent指向上级目录,为NULL时,默认为/proc目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值