设备模型三(潜谈sysfs)
来源:互联网 发布:网上商城java源码 编辑:程序博客网 时间:2024/06/11 05:52
- 前言
引出一个问题:假设 /sys/a/b/xx, xx是kobj b的属性文件, 当对xx进行写操作时,即echo ‘1’ > /sys/a/b/xx
实际上,调用了kobj b的ktype中定义的接口函数, 这一系列的流程涉及到
1.属性文件的创建函数 sysfs_create_file
2.sysfs的挂载
3.sysfs的读写操作
下面就围绕上面三点展开讨论 - sysfs的挂载
系统初始化时期已经将sysfs挂载上了形成了一颗独立的VFS树,我们来看看如何形成的,其实如果看了前面介绍的VFS的理解这篇文章,理解sysfs的挂载应该比较轻松
sysfs_init中
err = register_filesystem(&sysfs_fs_type);//注册文件系统 if (!err) { sysfs_mnt = kern_mount(&sysfs_fs_type);//挂载 if (IS_ERR(sysfs_mnt)) { printk(KERN_ERR "sysfs: could not mount!\n"); err = PTR_ERR(sysfs_mnt); sysfs_mnt = NULL; unregister_filesystem(&sysfs_fs_type); goto out_err; } }
很明显,根据代码, 注册完sysfs_fs_type文件系统后,紧接着挂载
static struct file_system_type sysfs_fs_type = { .name = "sysfs", .mount = sysfs_mount, //挂载函数 .kill_sb = sysfs_kill_sb,};
kern_mount函数会调用sysfs_mount函数
完成挂载后sysfs_dirent, inode, dentry三者关系
就是说,我们的sysfs的VFS树创建完毕
接下来讨论sysfs_create_file函数
流程下图所示:
sysfs_create_file(b的kobj, attr, “xx”)创建完之后, 仅仅是在sysfs的目录结构上建立了关系,但是并没有生成inode, 这个就很奇怪了啊,跟ext3的套路不一样我去,没关系,我们慢慢看, 我们可以看到sysfs_direct的对应关系(/sys/a/b/xx)如下图:
至此,创建文件就这样了sysfs的读写操作
话说本以为sysfs的读写操作跟其他VFS差不多,就是找dentry,获取inode,比如ext3文件系统,我在创建文件的时候inode已经生成了,但是sysfs不同, 通过调用sysfs_create_file之后,并没有生成indoe, 那什么时候生成inode呢? 是在打开文件的时候生成的inode..
对于文件的打开操作,在VFS的一文的讨论中并没有说明,接下来需讨论一下(依旧跟据上面的例子继续分析),看下图为当前的目录情况
当调用open函数时,调用关系如下图
上图给出了open的调用关系链,接下来看看inode, dentry, sysfs_direct 在open过程中的情况
讲到这里,个人认为基本上很清晰了,说来也奇怪, sysfs居然在open的时候才生成inode, 为什么这个设计不清楚啊,如果有谁知道请告知一下,万分感谢,不过想想有一点可以确认的是,这么作似乎在节省inode缓存空间的使用, 意图在用的时候生成inode,假设如果sysfs在创建文件的时候生成inode,那它所生成的inode基本上不会iput..,而像ext3这样的文件系统,基本上生成的文件(inode),写完就close了,close的时就iput了,所以..
之后调用完sysfs_lookup函数后, 调用__dentry_open函数,最后调用sysfs_open_file函数(VFS惯用伎俩),补充啰嗦一句, xx是文件类型(非目录),所以.open调用的是sysfs_open_file
static int sysfs_open_file(struct inode *inode, struct file *file){ struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; //大家可以看到这里的 attr_sd 就是 xx的sysfs_direct struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;//这里attr->sd_sparent是a的sd,这里获取的kobj是a的kobj,关于s_dir.kobj的赋值可以参考前一篇文章 struct sysfs_buffer *buffer; const struct sysfs_ops *ops; int error = -EACCES; /* need attr_sd for attr and ops, its parent for kobj */ if (!sysfs_get_active(attr_sd)) return -ENODEV; /* every kobject with an attribute needs a ktype assigned */ if (kobj->ktype && kobj->ktype->sysfs_ops) ops = kobj->ktype->sysfs_ops; //将a的ktype赋值给ops else { WARN(1, KERN_ERR "missing sysfs attribute operations for " "kobject: %s\n", kobject_name(kobj)); goto err_out; }
接着来
buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); //生成了一个buffer if (!buffer) goto err_out; mutex_init(&buffer->mutex); buffer->needs_read_fill = 1; buffer->ops = ops; //将ops扔进buffer中 file->private_data = buffer; //将buffer扔进file->private_data
这样open函数后, 在进行read或者write, 直接file->private_data->ops就可以了,如下图所示
其实就是操作xx,就是调用了a的ktype
总结:
此篇的讨论结束了,讨论了sysfs的挂载,以及读写脉络,最后贴出一张经典图
如上图sysfs超级块sysfs_sb、dentry根目录root、sysfs_direct根目录sysfs_root都是在sysfs初始化时创建。
sysfs_root下的子节点是添加设备对象或对象属性时调用sysfs_create_dir/ sysfs_create_file创建的,同时会申请对应的inode的索引号s_ino。注意此时并未创建inode。
inode是在用到的时候调用sysfs_get_inode函数创建并依据sysfs_sb地址和申请到的s_ino索引计算散列表位置放入其中。
dentry的子节点也是需要用的时候才会创建。比如open文件时,会调用path_walk根据路径一层层的查找指定dentry,如果找不到,则创建一个,并调用父dentry的inode的lookup函数(sysfs文件系统的为sysfs_lookup)查找对应的子inode填充指定的dentry。
说道这里大家可能对ktype还是没什么赶脚,没关系,带着问题继续往下看
- 设备模型三(潜谈sysfs)
- linux设备模型--sysfs
- 设备模型-sysfs
- Linux设备驱动模型 sysfs
- 设备模型3之sysfs
- Sysfs-设备模型上层容器
- linux下sysfs设备模型
- 设备驱动模型与sysfs
- 初识Linux设备驱动模型与sysfs(1)
- 统一设备模型(四):sysfs文件系统的分析
- sysfs文件系统与linux设备模型(5.4.2)
- 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动
- linux设备模型 —— sysfs
- Linux设备模型<一>认识Sysfs
- linux设备模型 —— sysfs
- Sysfs文件系统与Linux设备模型
- Linux-2.6设备模型与sysfs文件系统
- linux设备模型 —— sysfs
- windows下面自动打包exe批处理
- vue.js获取数据库数据
- 营救
- 如何使 vlc 支持 fdk-aac 编码(windows平台
- jstl的fmt标签(格式标签)
- 设备模型三(潜谈sysfs)
- 0-1背包(DP经典问题)
- 编写地道的go代码
- dubbo连接zookeeper注册中心因为断网导致线程无限等待问题
- Android sdk content loader 0%的解决方案
- Machine Learn on device performance (Tensor flow way)
- 自动评测(ROUGE)及及踩过的坑
- 成为Java顶尖程序员 ,看这10本书就够了
- freemarker 类型转换