------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:http://ericxiao.cublog.cn/
------------------------------------------
一:前言
在设备模型中,sysfs文件系统用来表示设备的结构.将设备的层次结构形象的反应到用户空间中.用户空间可以修改sysfs中的文件属性来修改设备的属性值,今天我们就来详细分析一下,sysfs的实现.
二:sysfs的初始化和挂载
Sysfs文件系统的初始化是在sysfs_init()中完成的,代码如下:
int __init sysfs_init(void)
{
int err = -ENOMEM;
//创建一个分配sysfs_dirent的cache
sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
sizeof(struct sysfs_dirent),
0, 0, NULL);
if (!sysfs_dir_cachep)
goto out;
err = sysfs_inode_init();
if (err)
goto out_err;
//注册sysfs文件系统s
err = register_filesystem(&sysfs_fs_type);
if (!err) {
//挂载sysfs文件系统
sysfs_mount = kern_mount(&sysfs_fs_type);
if (IS_ERR(sysfs_mount)) {
printk(KERN_ERR "sysfs: could not mount!\n");
err = PTR_ERR(sysfs_mount);
sysfs_mount = NULL;
unregister_filesystem(&sysfs_fs_type);
goto out_err;
}
} else
goto out_err;
out:
return err;
out_err:
kmem_cache_destroy(sysfs_dir_cachep);
sysfs_dir_cachep = NULL;
goto out;
}
每个kobject对应sysfs中的一个目录,kobject的每个属性对应sysfs文件系统中的文件.
struct sysfs_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域遍历即可.
当然,有时候也需要从struct sysfs_dirent导出它所属的dentry结点.我们在代码中遇到的时候再进行分析.
Sysfs文件系统的file_system_type定义如下:
static struct file_system_type sysfs_fs_type = {
.name = "sysfs",
.get_sb = sysfs_get_sb,
.kill_sb = kill_anon_super,
};
通过前面文件系统的相关分析,我们知道在sys_mount()中最终会调用struct file_system_type的get_sb函数来实现文件系统的挂载.它的代码如下:
static int sysfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
}
get_sb_single()的代码在前面已经涉及到,它对super_block.以及挂载的dentry和inode的赋值是在回调函数sysfs_fill_super, mnt()中完成的.代码如下:
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode;
struct dentry *root;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = SYSFS_MAGIC;
sb->s_op = &sysfs_ops;
sb->s_time_gran = 1;
sysfs_sb = sb;
/* get root inode, initialize and unlock it */
inode = sysfs_get_inode(&sysfs_root);
if (!inode) {
pr_debug("sysfs: could not get root inode\n");
return -ENOMEM;
}
/* instantiate and link root dentry */
root = d_alloc_root(inode);
if (!root) {
pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
iput(inode);
return -ENOMEM;
}
//将sysfs_root关联到root
root->d_fsdata = &sysfs_root;
sb->s_root = root;
return 0;
}
在这里要注意几个全局量. sysfs_sb表示sysfs文件系统的super_block. sysfs_root表示sysfs文件系统根目录的struct sysfs_dirent.
0
最新评论共有 0 位网友发表了评论
查看所有评论
发表评论
热点关注
- 移植uClinux-2.6.9到S3C44
- 基于Qt/Embedded和Qtopia
- 华恒ColdFire系列嵌入式Li
- Linux-2.6.20内核移植到AT
- qtopia-2.2.0的交叉编译以
- 我的MiniGUI移植之路
- Qtopia安装简要入门
- 嵌入式常用IC芯片索引
- skyeye安装移植uclinux
- 嵌入式系统开发学习如何起
- linux 2.6 下基于yl2440板
- The Linux MTD, JFFS HOWT
- 嵌入式 用户图形接口uC/GU
- QT/Embedded-3.3.8初步交
- LEOS嵌入式系统地实现过程
- 构造arm-linux交叉编译工
- 学会做嵌入式Linux操作系
- armlinux启动配置文件 /et
- 常见的嵌入式操作系统都有
- uC/OS-II系统应用开发
