sysfs文件系统之读写文件

11 篇文章 1 订阅
------------------------------------------------ 
#纯属个人理解,如有问题敬请谅解!

#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设备模型提供了条件.

 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux虚拟文件系统(Virtual File System,VFS)是Linux操作系统中的一个重要组成部分,它提供了一个统一的接口,使得用户和应用程序可以通过相同的方式访问不同类型的文件系统。 VFS的设计目标是将不同类型的文件系统抽象为一个统一的接口,使得用户和应用程序无需关心底层文件系统的具体实现细节。通过VFS,用户可以使用相同的系统调用(如open、read、write等)来访问不同类型的文件系统,包括本地文件系统(如ext4、XFS等)、网络文件系统(如NFS、CIFS等)以及虚拟文件系统(如procfssysfs等)。 VFS的核心数据结构是inode和dentry。inode(index node)表示文件或目录在文件系统中的索引节点,它包含了文件或目录的元数据信息,如权限、大小、时间戳等。dentry(directory entry)表示目录中的一个条目,它包含了文件或目录的名称和对应的inode指针。 VFS通过层次化的文件系统结构来管理不同类型的文件系统。在最顶层是一个虚拟文件系统层(VFS层),它提供了与用户和应用程序交互的接口。下面是一些常见的虚拟文件系统: 1. procfs:提供了对内核运行时信息的访问,以文件的形式呈现。用户可以通过读取procfs中的文件获取系统信息,如进程信息、内存信息等。 2. sysfs:提供了对设备和驱动程序的访问,以文件的形式呈现。用户可以通过sysfs获取和配置系统中的设备信息。 3. tmpfs:是一种基于内存的文件系统,它将文件存储在内存中而不是硬盘上,读写速度较快,适用于临时文件存储。 4. nfs:是一种网络文件系统,允许用户通过网络访问远程主机上的文件。 5. ext4、XFS等:是常见的本地文件系统,用于在硬盘上存储文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值