浅析sysfs文件系统注册流程
start_kernel
=>vfs_caches_init
=>mnt_init
=>sysfs_init
int __init sysfs_init(void)
{
int err = -ENOMEM;
//创建存放slab对象的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;
err = register_filesystem(&sysfs_fs_type);//注册sysfs文件系统控制信息
if (!err) {
//那么将sysfs文件系统mount上来
//sysfs文件系统是一个排它式的文件系统, 不论被mount多少次都只产生一个sb超级块,
//如果尝试再次mount,即尝试再次调用sysfs_get_sb获取另一个sb超级块,那么将执行atomic_inc(old->s_active);增加
//已被mount的引用计数,然后如果s已经执行了alloc_super,那么调用destroy_super将其销毁,然后返回这个已被mount了的
//super_block超级块old,这样就实现了sysfs文件系统 不论被mount多少次都只产生一个sb超级块的效果 ,所以取名为get_sb_single[luther.gliethttp] sysfs_mount = kern_mount(&sysfs_fs_type);
//http://blog.chinaunix.net/u1/38994/showart_1328541.html
//请参考: 《浅析kern_mount加载sysfs的流程》
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;
}
static struct file_system_type sysfs_fs_type = {
.name = "sysfs",
.get_sb = sysfs_get_sb,
.kill_sb = kill_anon_super,
};
//所有注册登记的文件系统结构体都链接到一个以file_systems开头的单向链表中[luther.gliethttp]
int register_filesystem(struct file_system_type * fs)
{
int res = 0;
struct file_system_type ** p;
BUG_ON(strchr(fs->name, '.'));
if (fs->next)
return -EBUSY;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name));
if (*p)//该文件系统已经存在了
res = -EBUSY;
else
*p = fs;//将fs挂到这个以file_systems开头的单向链表上[luther.gliethttp]
write_unlock(&file_systems_lock);
return res;
}
//顺序扫描file_systems这个单向链表,查找名为name的文件系统是否已经注册
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strlen((*p)->name) == len &&
strncmp((*p)->name, name, len) == 0)
break;
return p;
}
|