Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186457
  • 博文数量: 87
  • 博客积分: 2975
  • 博客等级: 少校
  • 技术积分: 926
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-24 17:14
文章分类

全部博文(87)

文章存档

2010年(87)

我的朋友

分类: LINUX

2010-09-21 11:52:40

跟上回一样,我用这个小程序来读 #include
#include
#include
int main()...{
              char *name = "/sys/bus/ldd/version";
              char buf[500];
              int fd;
              int size;
              fd = open(name, O_RDONLY);
              printf("fd:%d ",fd);
              size = read(fd,buf,sizeof(buf));
              printf("size:%d ",size);
              printf("%s",buf);
              close(fd);
              return -1;
}
(1)sysfs_open_file()
open() ->/*用户空间*/
-> 系统调用->
sys_open() -> filp_open()-> dentry_open() -> sysfs_open_file()/*内核空间*/
static int sysfs_open_file(struct inode * inode, struct file * filp)
{
             return check_perm(inode,filp);
}
static int check_perm(struct inode * inode, struct file * file)
...{
    struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
    struct attribute * attr = to_attr(file->f_dentry);
    struct sysfs_buffer * buffer;
    struct sysfs_ops * ops = NULL;
    int error = 0;
    if (!kobj || !attr)
        goto Einval;
    /**//* Grab the module reference for this attribute if we have one */
    if (!try_module_get(attr->owner)) ...{
        error = -ENODEV;
        goto Done;
    }
    /**//* if the kobject has no ktype, then we assume that it is a subsystem
     * itself, and use ops for it.
     */
    if (kobj->kset && kobj->kset->ktype)
        ops = kobj->kset->ktype->sysfs_ops;
    else if (kobj->ktype)
        ops = kobj->ktype->sysfs_ops;
    else
        ops = &subsys_sysfs_ops;
    /**//* No sysfs operations, either from having no subsystem,
     * or the subsystem have no operations.
     */
    if (!ops)
        goto Eaccess;
    /**//* File needs write support.
     * The inode's perms must say it's ok,
     * and we must have a store method.
     */
    if (file->f_mode & FMODE_WRITE) ...{
        if (!(inode->i_mode & S_IWUGO) || !ops->store)
            goto Eaccess;
    }
    /**//* File needs read support.
     * The inode's perms must say it's ok, and we there
     * must be a show method for it.
     */
    if (file->f_mode & FMODE_READ) ...{
        if (!(inode->i_mode & S_IRUGO) || !ops->show)
            goto Eaccess;
    }
    /**//* No error? Great, allocate a buffer for the file, and store it
     * it in file->private_data for easy access.
     */
    buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL);
    if (buffer) ...{
        memset(buffer,0,sizeof(struct sysfs_buffer));
        init_MUTEX(&buffer->sem);
        buffer->needs_read_fill = 1;
        buffer->ops = ops;
        file->private_data = buffer;
    } else
        error = -ENOMEM;
    goto Done;
 Einval:
    error = -EINVAL;
    goto Done;
 Eaccess:
    error = -EACCES;
    module_put(attr->owner);
 Done:
    if (error && kobj)
        kobject_put(kobj);
    return error;
}
check_perm()检查一下权限,创建一个sysfs的缓冲区sysfs_buffer buffer,并设置其sysfs_ops sysfs_buffer->ops。在我们这个故事里,sysfs_buffer->ops被设置成bus_sysfs_ops。最后让file->private_data = buffer。
(2)sysfs read file()
流程如下:
read()->/*用户空间*/
-> 系统调用->
sys_read() -> vfs_read() -> sysfs_read_file()/*内核空间*/
看看sysfs_read_file()函数,
static ssize_t
sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
...{
    struct sysfs_buffer * buffer = file->private_data;
    ssize_t retval = 0;
    down(&buffer->sem);
    if (buffer->needs_read_fill) ...{
        if ((retval = fill_read_buffer(file->f_dentry,buffer)))
            goto out;
    }
    pr_debug("%s: count = %d, ppos = %lld, buf = %s ",
         __FUNCTION__,count,*ppos,buffer->page);
    retval = flush_read_buffer(buffer,buf,count,ppos);
out:
    up(&buffer->sem);
    return retval;
}
顺着sysfs_read_file()往下走:
sysfs_read_file()
              ---> fill_read_buffer()
                            ---> sysfs_buffer->bus_sysfs_ops->bus_attr_show()
                                        ---> bus_attribute->show_bus_version() //注意这个函数是我们在lddbus.c里面定义的
              ---> flush_read_buffer()
fill_read_buffer()的是真正的读,它把内容读到sysfs定义的缓冲区sysfs_buffer。flush_read_buffer()是把缓冲区copy到用户空间。
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fudan_abc/archive/2007/09/14/1785497.aspx
阅读(1896) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-21 16:08:51

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com