这个文件系统主要作用是:在用户态展示设备的信息。
4.1 文件和目录的创建
4.1.1 文件系统的初始化。
sysfs_init()
int __init sysfs_init(void)
{
sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
________________ sizeof(struct sysfs_dirent),
________________ 0, 0, NULL, NULL);
......
err = register_filesystem(&sysfs_fs_type);
if (!err) {
____sysfs_mount = kern_mount(&sysfs_fs_type);
......
}
......
}
4.1.2 sys文件系统目录的创建。
sysfs_create_dir->create_dir->lookup_one_len
->sysfs_make_dirent->sysfs_new_dirent(parent_sd, element) /* 创建一个新的sysfs_dirent */
->sysfs_create-> /* 1)为目录文件创建一个inode对象,
2)并初始化inode对应的两个操作函数
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations; */
4.1.3 普通文件的创建。
sysfs_create_file->sysfs_add_file->sysfs_make_dirent /* sys文件系统到目前为止,只为文件的创建了一个sysfs_dirent;而文件系统创建文件需要为文件创建一个inode和dentry,接下来在文件打开的过程中会创建需要的inode和dentry。 */
4.2 sysfs文件的打开过程。
在VFS虚拟文件系统文件的打开过程中,实际是将文件的整个路径名层层解析,最终找到文件的过程。如果文件曾经被打开过,则在dentry cache中可能保存文件的dentry结构,如果在dentry cache中找不到文件,则调用real_lookup,通过real_lookup函数再调用文件系统相关的lookup函数。
static int do_lookup(struct nameidata *nd, struct qstr *name,
________ struct path *path)
{
____struct vfsmount *mnt = nd->mnt;
____struct dentry *dentry = __d_lookup(nd->dentry, name);
____if (!dentry)
________goto need_lookup;
____if (dentry->d_op && dentry->d_op->d_revalidate)
________goto need_revalidate;
done:
____path->mnt = mnt;
____path->dentry = dentry;
______follow_mount(path);
____return 0;
need_lookup:
____dentry = real_lookup(nd->dentry, name, nd);
____if (IS_ERR(dentry))
________goto fail;
____goto done;
need_revalidate:
____if (dentry->d_op->d_revalidate(dentry, nd))
________goto done;
____if (d_invalidate(dentry))
________goto done;
____dput(dentry);
____goto need_lookup;
fail:
____return PTR_ERR(dentry);
}
/*
* This is called when everything else fails, and we actually have
* to go to the low-level filesystem to find out what we should do..
....
*/
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
mutex_lock(&dir->i_mutex);
/* 再次搜索一边dentry cache是为了防止在等信号量时,其他用户已经创建 */
result = d_lookup(parent, name);
if (!result) {
____struct dentry * dentry = d_alloc(parent, name);
____result = ERR_PTR(-ENOMEM);
____if (dentry) {
________result = dir->i_op->lookup(dir, dentry, nd);
________if (result)
____________dput(dentry);
________else
____________result = dentry;
____}
____mutex_unlock(&dir->i_mutex);
____return result;
}
mutex_unlock(&dir->i_mutex);
......
}
对于sysfs文件系统来说,lookup函数就是sysfs_lookup.在执行具体文件系统(sys)的相关的lookup之前会创建一个dentry,通过这个entry,sysfs_lookup会找到它的父sysfs_dirent,遍历父sysfs_dirent下的各个子sysfs_dirent,直到找到对应的子sysfs_dirent.接下来就是创建对应的inode,完成real_lookup的查找工作。
以上可以理解为VFS层对文件的处理,接下来才是sys文件系统真正的打开文件的函数sys_open_file->check_perm。
static int sysfs_open_file(struct inode * inode, struct file * filp)
{
____return check_perm(inode,filp);
}
check_perm分两部分:
1)文件权限的检查。
普通文件会有attribute结构,目录文件会有kobject结构,如果目录文件的kobject提供了文件的操作函数,普通文件要赋值为kobject结构提供的操作函数,如果没有文件的操作函数则复制为子系统的操作函数指针,然后根据文件的inode->imode进行文件的权限检查。
/* if the kobject has no ktype, then we assume that it is a subsystem
* itself, and use ops for it.
*/
if (kobj->kset && kobj->kset->ktype)
____ops = kobj->kset->ktype->sysfs_ops;
else if (kobj->ktype)
____ops = kobj->ktype->sysfs_ops;
else
____ops = &subsys_sysfs_ops;
2)创建文件的私有数据结构(file->private_data)。
这是文件对象中保存文件系统特殊信息的方式。
/* No error? Great, allocate a buffer for the file, and store it
* it in file->private_data for easy access.
*/
buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
if (buffer) {
____init_MUTEX(&buffer->sem);
____buffer->needs_read_fill = 1;
____buffer->ops = ops;
____file->private_data = buffer;
}