Linux sysfs open, read and write files of sysfs file system

The above article analyzes the creation process of files in sysfs. Since the file has been established, reading and writing it is our ultimate goal. This article will take a look at how sysfs can read and write files under sysfs through the VFS interface.

sysfs attribute file operation method

In the function sysfs_init_inode(), the operation method of the sysfs attribute file is initialized as sysfs_file_operations. Next, the operation method of the attribute file is used to analyze the sysfs file reading and writing process.

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,

};

How VFS transfers to these callback functions has been analyzed in previous articles. Let's take a look at these functions directly.

How to achieve......

sysfs open properties file

The attribute file open operation function defined by sysfs is 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;

330

331         /* need attr_sd for attr and ops, its parent for kobj */

332         if (!sysfs_get_active_two(attr_sd))

333                 return -ENODEV;

334

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         }

344

……………………

366         error = -ENOMEM;

367         buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);

368         if (!buffer)

369                 goto err_out;

370

371         mutex_init(&buffer->mutex);

372         buffer->needs_read_fill = 1;

373         buffer->ops = ops;

374         file->private_data = buffer;

375

376         /* make sure we have open dirent struct */

377         error = sysfs_get_open_dirent(attr_sd, buffer);

378         if (error)

379                 goto err_free;

380

381         /* open succeeded, put active references */

382         sysfs_put_active_two(attr_sd);

383         return 0;

384

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;

130

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",

138                  __func__, count, *ppos, buffer->page);

139         retval = simple_read_from_buffer(buf, count, ppos, buffer->page,

140                                          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;

230

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324084975&siteId=291194637