处理基本文件的索引节点操作
对于pid文件夹里面的文件(/proc/pid)索引节点统一,内核静态地定义proc_base_inode_operations作为索引节点操作,定义如下:
- //索引节点操作
-
static const struct inode_operations proc_tgid_base_inode_operations = {
-
.lookup = proc_tgid_base_lookup,
-
.getattr = pid_getattr,//直接将参数dentry的属性赋值给指定的文件
-
.setattr = proc_setattr,//修改dentry的属性
-
}
-
//文件操作
-
static const struct file_operations proc_tgid_base_operations = {
-
.read = generic_read_dir,
-
.readdir = proc_tgid_base_readdir,
-
}
每个pid中的项定义如下:
- struct pid_entry {
-
char *name;
-
ine len;
-
mode_t mode;
-
const struct inode_operaions *iop;
-
const struct file_operation *fop;
-
union proc_op op;
-
}
lookup定义如下:
- static struct *proc_tgid_base_lookup(struct inode *dir,struct dentry*dentry,struct nameidata *nd)
-
{
-
//tgid_base_stuff:规定pid文件夹中的所有子文件夹项,及相应的处理函数,不同的文件夹不同的文
-
//件处理函数,但都类似
-
return proc_pident_lookup(dir,dentry,tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
-
}
而具体的调用函数proc_pident_lookup定义如下:
- //在ents文件夹中查找dentry的目录项
-
static struct dentry *proc_pident_lookup(struct inode* dir,struct dentry *dentry,const struct pid_entry *ents,unsigned int nents)
-
{
-
struct inode *inode;
-
struct dentry *error;
-
struct task_struct *task = get_proc_task(dir);
-
const struct pid_entry *p,*last;
-
-
error = ERR_PTR(-ENOENT);
-
inode = NULL;
-
-
if(!task)
-
goto out_no_task;
-
-
last = &ents[nents-1];
-
//进行遍历查找
-
for(p=ents;p<=last;p++){
-
if(p->len != dentry->d_name.len) continue;
-
if(!memcpy(dentry->d_name.name,p->name,p->len)) break;
-
}
-
if(p->last) goto out_no_break;
-
//创建索引节点,并进行缓存
-
error = proc_pident_instantiate(dir,dentry,task,p);
-
out:
-
put_task_struct(task);
-
out_no_task:
-
return error;
-
}
readdir函数原型如下:
- //从filp文件中读取一项填入dirent
-
static int proc_tgid_base_readdir(struct file* filp,void *dirent,filldir_t filldir)
-
{
-
return proc_pident_readdir(filp,dirent,filldir,tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
-
}
具体执行函数如下:
- //在ents中读取文件,filldir_t定义为:typedef int (*filldir_t)(void*,const char*,int,loff_t,ino_t,unsigned);
-
static int proc_pident_readdir(struct file* filep,
-
void *dirent,filldir_t filldir,const struct pid_entry *ents,unsigned int nents)
-
{
-
int i;
-
//与文件相对应的dentry
-
struct dentry *dentry = filp->f_path.entry;
-
//找出对应的索引节点
-
struct inode *inode = dentry ->d_inode;
-
//找出pid
-
struct task_struct *task = get_proc_task(inode);
-
const struct pid_entry *p,*last;
-
ino_t ino;
-
int ret;
-
-
ret = -ENOENT;
-
if(!task)
-
goto out_no_task;
-
-
ret = 0;
-
//当前文件偏移量
-
i = filp->f_pos;
-
switch(i){
-
//最开始就是.,表示本目录
-
case 0:
-
ino = inode->i_ino;
-
if(filldir(dirent,”.”,1,i,ino,DT_DIR)<0) goto out;
-
-
i++;
-
filp->f_pos++;
-
//接着指向父目录
-
case 1:
-
ino = parent_ino(dentry);
-
//写入具体的空间
-
if(filldir(dirent,”..”,2,i,ino,DT_DIR)<0) goto out;
-
-
i++;
-
filp->f_pos++;
-
default:
-
i -=2;
-
if( i>= nents) {
-
ret = 1;
-
goto out;
-
} //找出偏移量,则对应具体文件夹
-
p = ents+i;
-
last = &ents[nents-1];
-
while(p<=last){
-
//找到之后,写入缓存中,再调用filldir写入dirent
-
if(proc_pident_fill_cache(filp,dirent,filldir,task,p)<0)
-
goto out;
-
//写完之后位置添加,看来一次性读完pid文件夹下的文件
-
filp->f_pos++;
-
p++;
-
}
-
}
-
ret = 1;
-
out: put_task_struct(task);
-
-
out_no_task:
-
return ret;
-
}
/proc文件操作接口
/proc是一个文件系统,它不仅可以显示系统的状态,也可以方便其它驱动注册自己的文件夹,这些函数接口如下:
常见的操作函数有:
创建文件:
struct proc_dir_entry *create_proc_entry(const char *name,mode_t
mode, struct proc_dir_entry *parent)
函数原型如下:
- struct proc_dir_entry *create_proc_entry(const char* name,mode_t mode,
-
struct proc_dir_entry *parent)
-
{
-
…....
-
//利用slab分配器分配struct proc_dir_entry结构体,进行部分初始化
-
ent = proc_creat(&parent,name,mode,nlink);
-
-
if(ent) {
-
//针对不同类型的文件,实行不同的函数操作,并实现父子目录的连接
-
if(proc_register(parent,ent)<0) {
-
kfree(ent);
-
en = NULL;
-
}
-
}
-
}
除了上面的函数可以进行创建文件之外,下面的函数也可以进行创建,只不过进行了简单的封装:
- //创建文件之外,注册了读取函数read_proc和数据项,而inode中的read函数最终也是指向read_proc
-
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)
-
//创建文件之后,注册get_info指针
-
struct proc_dir_entry * create_proc_info_entry(const char* name,
-
mode_t mode,struct proc_dir_entry* base,get_info_t *get_info)
创建文件夹
- struct proc_dir_entry* proc_mkdir(const char*name,struct proc_dir_entry* parent);
-
struct proc_dir_entry* proc_mkdir_mode(const char*name,
-
mode_t mode,struct proc_dir_entry* parent);
阅读(3884) | 评论(0) | 转发(2) |