sysfs文件系统之读写文件

xiaoxiao2021-02-28  88

------------------------------------------------ #纯属个人理解,如有问题敬请谅解! #kernel version: 2.6.26 #Author: andy wang ------------------------------------------------- 上面的文章分析了sysfs中文件的创建过程, 既然文件已经建立起来了,读写它才是我们最终的目的撒,本文就来看看sysfs是咋个通过VFS接口读写sysfs下的文件. sysfs属性文件操作方法 在函数sysfs_init_inode()中初始化了sysfs属性文件的操作方法为sysfs_file_operations, 下面就拿属性文件操作方法分析sysfs文件读写流程. const struct file_operations sysfs_file_operations = { .read = sysfs_read_file, .write = sysfs_write_file, .llseek = generic_file_llseek, .open = sysfs_open_file, .release = sysfs_release, .poll = sysfs_poll, }; 关于VFS是如何调到这些回调函数的,在以前的文章中已经分析过了哦,我们下面直接来看看这些函数是 如何实现的......... sysfs打开属性文件 sysfs定义的属性文件打开操作函数为sysfs_open_file() 323 static int sysfs_open_file(struct inode *inode, struct file *file) 324 { 325 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 326 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 327 struct sysfs_buffer *buffer; 328 struct sysfs_ops *ops; 329 int error = -EACCES; 331 /* need attr_sd for attr and ops, its parent for kobj */ 332 if (!sysfs_get_active_two(attr_sd)) 333 return -ENODEV; 335 /* every kobject with an attribute needs a ktype assigned */ 336 if (kobj->ktype && kobj->ktype->sysfs_ops) 337 ops = kobj->ktype->sysfs_ops; 338 else { 339 printk(KERN_ERR "missing sysfs attribute operations for " 340 "kobject: %s\n", kobject_name(kobj)); 341 WARN_ON(1); 342 goto err_out; 343 } …………………… 366 error = -ENOMEM; 367 buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); 368 if (!buffer) 369 goto err_out; 371 mutex_init(&buffer->mutex); 372 buffer->needs_read_fill = 1; 373 buffer->ops = ops; 374 file->private_data = buffer; 376 /* make sure we have open dirent struct */ 377 error = sysfs_get_open_dirent(attr_sd, buffer); 378 if (error) 379 goto err_free; 381 /* open succeeded, put active references */ 382 sysfs_put_active_two(attr_sd); 383 return 0; 385 err_free: 386 kfree(buffer); 387 err_out: 388 sysfs_put_active_two(attr_sd); 389 return error; 390 } 第325-326行函数的目的就是要取出当前文件 父目录对应的kobj对象 第337行代码就是操作sysfs文件的关键地方了,ops = kobj->ktype->sysfs_ops;从这段代码可以看出sysfs文件的操作方法实际上用的是该文件父目录的kobj关联的ktype中定义的sysfs_ops操作方法 struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; 可以看到sysfs下的属性文件只定义了show和store方法. 第367-374行, 先是分配一个sysfs_buffer结构并将上面取到的文件操作方法ops 初始化给buffer->ops,,最后再将buffer结构初始化给file->private_data ,这样我们在后面的读和写中就可以取到它的信息了. sysfs读属性文件 在打开了文件以后再看看怎么读这个文件. 125 static ssize_t 126 sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) 127 { 128 struct sysfs_buffer * buffer = file->private_data; 129 ssize_t retval = 0; 131 mutex_lock(&buffer->mutex); 132 if (buffer->needs_read_fill || *ppos == 0) { 133 retval = fill_read_buffer(file->f_path.dentry,buffer); 134 if (retval) 135 goto out; 136 } 137 pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",__func__, count, *ppos, buffer->page); 139 retval = simple_read_from_buffer(buf, count, ppos, buffer->page,buffer->count); 141 out: 142 mutex_unlock(&buffer->mutex); 143 return retval; 144 } 第128行先取出刚才打开时建立的buffer结构. 第133行fill_read_buffer()函数就是调用buffer->ops->show()文件读操作,读到的数据在buffer->page 第139行函数simple_read_from_buffer()函数很简单,这个函数就是把我们读到的数据拷贝到用户空间 ,实现与用户空间的数据交互. sysfs写属性文件 sysfs属性文件的写操作和读操作都是差不多的. 225 static ssize_t 226 sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 227 { 228 struct sysfs_buffer * buffer = file->private_data; 229 ssize_t len; 231 mutex_lock(&buffer->mutex); 232 len = fill_write_buffer(buffer, buf, count); 233 if (len > 0) 234 len = flush_write_buffer(file->f_path.dentry, buffer, len); 235 if (len > 0) 236 *ppos += len; 237 mutex_unlock(&buffer->mutex); 238 return len; 239 } 第232行函数首先需要把用户空间的数据拷贝到内核空间 第234行,调用ops->store()写操作回调函数 . 到这里sysfs文件的创建读写操作分析就已经完成了 ,这些都是理解linux设备模型的基础, 也为深入研究linux设备模型提供了条件.
转载请注明原文地址: https://www.6miu.com/read-47052.html

最新回复(0)