Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145338
  • 博文数量: 19
  • 博客积分: 1746
  • 博客等级: 上尉
  • 技术积分: 443
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-22 22:54
文章分类
文章存档

2011年(3)

2010年(16)

分类: LINUX

2010-03-03 17:23:44

------------------------------------------------
#纯属个人理解,如有问题敬请谅解!
#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;
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下的属性文件只定义了showstore方法.
 
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结构.
133fill_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设备模型提供了条件.
 
阅读(3323) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~