sysfsWord文档下载推荐.docx
《sysfsWord文档下载推荐.docx》由会员分享,可在线阅读,更多相关《sysfsWord文档下载推荐.docx(26页珍藏版)》请在冰豆网上搜索。
err=register_filesystem(&
sysfs_fs_type);
if(!
err){
//挂载sysfs文件系统
sysfs_mount=kern_mount(&
if(IS_ERR(sysfs_mount)){
printk(KERN_ERR"
sysfs:
couldnotmount!
\n"
);
err=PTR_ERR(sysfs_mount);
sysfs_mount=NULL;
unregister_filesystem(&
}
}else
out:
returnerr;
out_err:
kmem_cache_destroy(sysfs_dir_cachep);
sysfs_dir_cachep=NULL;
gotoout;
}
每个kobject对应sysfs中的一个目录,kobject的每个属性对应sysfs文件系统中的文件.
structsysfs_dirent就是用来做kobject与dentry的互相转换用的.它们的关系如下图所示:
上图表示的是一个kobject的层次结构.dentry的d_fsdata字段指定该结点所表示的
sysfs_dirent.sysfs_dirent.s_parent表示它的父kobject.sysfs_dirent.s_sibling表示它的兄弟结点.
sysfs_dirent.s_dir.children表示它所属的子节点.
从上图可知.如果要遍历一个结点下面的子结点,只需要找到sysfs_dirent.s_dir.children结点
然后按着子节点的s_sibling域遍历即可.
当然,有时候也需要从structsysfs_dirent导出它所属的dentry结点.我们在代码中遇到的时候再进行分
析.
Sysfs文件系统的file_system_type定义如下:
staticstructfile_system_typesysfs_fs_type={
.name
="
sysfs"
.get_sb
=sysfs_get_sb,
.kill_sb
=kill_anon_super,
};
通过前面文件系统的相关分析,我们知道在sys_mount()中最终会调用structfile_system_type的get_sb
函数来实现文件系统的挂载.它的代码如下:
staticintsysfs_get_sb(structfile_system_type*fs_type,
intflags,constchar*dev_name,void*data,structvfsmount*mnt)
returnget_sb_single(fs_type,flags,data,sysfs_fill_super,mnt);
get_sb_single()的代码在前面已经涉及到,它对super_block.以及挂载的dentry和inode的赋值是在回调
函数sysfs_fill_super,mnt()中完成的.代码如下:
staticintsysfs_fill_super(structsuper_block*sb,void*data,intsilent)
structinode*inode;
structdentry*root;
sb->
s_blocksize=PAGE_CACHE_SIZE;
s_blocksize_bits=PAGE_CACHE_SHIFT;
s_magic=SYSFS_MAGIC;
s_op=&
sysfs_ops;
s_time_gran=1;
sysfs_sb=sb;
/*getrootinode,initializeandunlockit*/
inode=sysfs_get_inode(&
sysfs_root);
inode){
pr_debug("
couldnotgetrootinode\n"
return-ENOMEM;
/*instantiateandlinkrootdentry*/
root=d_alloc_root(inode);
root){
%s:
couldnotgetrootdentry!
__FUNCTION__);
iput(inode);
//将sysfs_root关联到root
root->
d_fsdata=&
sysfs_root;
s_root=root;
return0;
在这里要注意几个全局量.sysfs_sb表示sysfs文件系统的super_block.sysfs_root表示sysfs文件系统
根目录的structsysfs_dirent.
sysfs_get_inode(&
sysfs_root)用来将sysfs_root导出相应的inode.代码如下:
structinode*sysfs_get_inode(structsysfs_dirent*sd)
//以super_block和sd->
s_ino为哈希值,到哈希表中寻找相应的inode.如果不存在,则新建
inode=iget_locked(sysfs_sb,sd->
s_ino);
//对新生成的inode进行初始化
if(inode&
&
(inode->
i_state&
I_NEW))
sysfs_init_inode(sd,inode);
returninode;
首先,它以sysfs文件系统的super_block和structsysfs_dirent.的s_ino成员的值做为哈希值到哈希表中
寻找相应的inode.如果在哈希表中不存在这个inode,那就新建一个,并将它链入到哈希表.之后,调用
sysfs_init_inode()对生成的inode进行初始化.显然.在mount的时候是不会生成inode的.必定会进入
sysfs_init_inode()函数.代码如下:
staticvoidsysfs_init_inode(structsysfs_dirent*sd,structinode*inode)
structbin_attribute*bin_attr;
inode->
i_blocks=0;
i_mapping->
a_ops=&
sysfs_aops;
backing_dev_info=&
sysfs_backing_dev_info;
i_op=&
sysfs_inode_operations;
i_ino=sd->
s_ino;
lockdep_set_class(&
i_mutex,&
sysfs_inode_imutex_key);
if(sd->
s_iattr){
/*sysfs_direnthasnon-defaultattributes
*getthemforthenewinodefrompersistentcopy
*insysfs_dirent
*/
set_inode_attr(inode,sd->
s_iattr);
set_default_inode_attr(inode,sd->
s_mode);
/*initializeinodeaccordingtotype*/
switch(sysfs_type(sd)){
caseSYSFS_DIR:
i_op=&
sysfs_dir_inode_operations;
i_fop=&
sysfs_dir_operations;
i_nlink=sysfs_count_nlink(sd);
break;
caseSYSFS_KOBJ_ATTR:
i_size=PAGE_SIZE;
i_fop=&
sysfs_file_operations;
caseSYSFS_KOBJ_BIN_ATTR:
bin_attr=sd->
s_bin_attr.bin_attr;
i_size=bin_attr->
size;
bin_fops;
caseSYSFS_KOBJ_LINK:
sysfs_symlink_inode_operations;
default:
BUG();
unlock_new_inode(inode);
在这里,我们可以看到sysfs文件系统中的各种操作函数了..
在syfs文件系统中,怎么样判断一个目录下是否有这个文件呢?
在前面有关文件系统的分析中我们可以看.有关文件的查找实际上都会由inod->
i_op->
lookup()函数进行
判断.在sysfs中,这个函数对应为sysfs_lookup().代码如下:
staticstructdentry*sysfs_lookup(structinode*dir,structdentry*dentry,
structnameidata*nd)
structdentry*ret=NULL;
//取得父结点对应的sysfs_dirent
structsysfs_dirent*parent_sd=dentry->
d_parent->
d_fsdata;
structsysfs_dirent*sd;
mutex_lock(&
sysfs_mutex);
//父结点的sysfs_dirent中是否有相应的子结点
sd=sysfs_find_dirent(parent_sd,dentry->
d_name.name);
/*nosuchentry*/
//如果没有.这个结点是不存在的
sd){
ret=ERR_PTR(-ENOENT);
gotoout_unlock;
/*attachdentryandinode*/
//如果有这个结点,为之生成inod结构.
inode=sysfs_get_inode(sd);
ret=ERR_PTR(-ENOMEM);
/*instantiateandhashdentry*/
dentry->
d_op=&
sysfs_dentry_ops;
//关联dentry与sysfs_dirent
d_fsdata=sysfs_get(sd);
d_instantiate(dentry,inode);
d_rehash(dentry);
out_unlock:
mutex_unlock(&
returnret;
由此可见,它的判断会转入到相应的sysfs_dirent中进行判断.如果设备模型在创建目录/文件的时候并不
会创建dentry或者inode.只会操作sysfs_dirent结构.如果找到了这个结构,就为这个结构生成inode.并
将其关联到denry中.
sysfs_find_dirent()如下:
structsysfs_dirent*sysfs_find_dirent(structsysfs_dirent*parent_sd,
constunsignedchar*name)
for(sd=parent_sd->
s_dir.children;
sd;
sd=sd->
s_sibling)
strcmp(sd->
s_name,name))
returnsd;
returnNULL;
它用的搜索方法就是我们在之前分析sysfs_dirent结构所讲述的.分析到这里,sysfs的大概轮廓就出现在
我们的眼前了.^_^.接下来分析sysfs文件系统中目录的创建过程
三:
在sysfs文件系统中创建目录
在linux设备模型中,每注册一个kobject.就会为之创建一个目录.具体的流程在分析linux设备模型的时候
再给出详细的分析.创建目录的接口为:
sysfs_create_dir().代码如下:
intsysfs_create_dir(structkobject*kobj)
structsysfs_dirent*parent_sd,*sd;
interror=0;
BUG_ON(!
kobj);
//如果kobject没有指定父结点,则将其父结点指定为sysfs的根目录syfs_root
if(kobj->
parent)
parent_sd=kobj->
parent->
sd;
else
parent_sd=&
//创建目录
error=create_dir(kobj,parent_sd,kobject_name(kobj),&
sd);
//kobj->
sd指向对应的sysfs_dirent
error)
kobj->
sd=sd;
returnerror;
在这里,先为结点指定父目录,然后调用create_dir()在父目录下生成结点.代码如下:
staticintcreate_dir(structkobject*kobj,structsysfs_dirent*parent_sd,
constchar*name,structsysfs_dirent**p_sd)
//指定目录的模式
umode_tmode=S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO;
structsysfs_addrm_cxtacxt;
intrc;
/*allocate*/
//分配并初始化一个sysfs_dirent
sd=sysfs_new_dirent(name,mode,SYSFS_DIR);
sd)
//初始化sd->
s_dir.kobj字段
sd->
s_dir.kobj=kobj;
/*linkin*/
//acxt是一个临时变量.它用来存放父结点的相关信息
//设置acxt->
parent_sd
为父结点的sysfs_dirent.acxt->
parent_inode为父结点的inode
sysfs_addrm_start(&
acxt,parent_sd);
//设置sd->
s_parent.并按inod值按顺序链入父结点的children链表
rc=sysfs_add_one(&
acxt,sd);
sysfs_addrm_finish(&
acxt);
if(rc==0)
*p_sd=sd;
sysfs_put(sd);
returnrc;
在这里,为子节点生成了对应的sysfs_dirent.设置了它的父结点域,并将其链入到父结点的children链表.
这样,在文件系统中查找父目录下面的子结点了.
四:
在sysfs中创建一般属性文件
Kobject的每一项属性都对应在sysfs文件系统中,kobject对应的目录下的一个文件.文件名称与属性名称
相同.创建一般属性的接口为sysfs_create_file().代码如下:
intsysfs_create_file(structkobject*kobj,conststructattribute*attr)
kobj||!
sd||!
attr);
//kobject->
sd:
为kobject表示目录的structsysfs_dirent结构
returnsysfs_add_file(kobj->
sd,attr,SYSFS_KOBJ_ATTR);
最终会调用sysfs_add_file().参数attr.是要生成文件的属性值.
intsysfs_add_file(structsysfs_dirent*dir_sd,conststructattribute*attr,
inttype)
//文件对应的属性
umode_tmode=(attr->
mode&
S_IALLUGO)|S_IFREG;
//创建一个新的sysfs_dirent.对应的名称为attr->
name.即属性的名称
sd=sysfs_new_dirent(attr->
name,mode,type);