sysfs文件系统之读写文件

本文详细解析了Linux sysfs文件系统的文件操作流程,包括文件打开、读取和写入的具体实现,介绍了sysfs属性文件如何利用VFS接口进行读写,并深入分析了sysfs_file_operations中的关键函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------------------------------------------------ 
#纯属个人理解,如有问题敬请谅解!

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

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值