• 20150223 IMX257 设备驱动模型之Kobject(一)


    20150223 IMX257 设备驱动模型之Kobject(一)

    2015-02-23 李海沿

    接下来我们开始涉及设备驱动模型,从简入深,我们先写一个驱动,实现的功能就是在sys目录下建立一个目录和一个属性文件,可读可写。

    所以今天的任务就是把这个程序搞定,只要把这几个结构体了解,知道有这个结构体就够了,很晚了,剩下的我们交给明天吧。

    一、结构体参数解释

    1. kobject

    kobject是设备驱动模型的基础。sysfs是基于kobject建立起来的。

    struct kobject{

        const char *name; //显示在sysfs中的名称

        struct list_head entry;    //下一个kobject结构

        struct kobject *parent;    //指向父kobject结构体,如果存在

        struct kset   *kset;     //指向kset集合

        struct kobj_type  *ktype; //指向kobject类型描述符

        struct sysfs_dirent *sd; //对应sysfs的文件目录

        struct kref kref;         //kobject引用计数

        unsigned int state_initialized:1; //是否初始化

        unsigned int state_in_sysfs:1; //是否加入sysfs

        unsigned int state_add_uevent_sent:1; //是否支持热插

        unsigned int state_remove_uevent_sent:1; //是否支持热拔

    }

    2. kobj_type

    每个kobject都会有一个属性kobj_type

    struct kobj_type

    {

      void (*release)(struct kobject *kobj); //释放kobject和其他占用资源的函数

      struct sysfs_ops *sysfs_ops;       //操作属性的方法

      struct attribute **default_attrs;     //属性数组

    };

    3. sysfs_ops

    struct sysfs_ops{

      ssize_t (*show)(struct kobject *,struct attribute *,char *);  //读属性操作函数

      ssize_t (*store)(struct kobject *,struct attribute *,const char *,size_t); //写属性操作函数

    };

    4. 描述属性文件的结构

    sysfs文件系统中,最重要的就是struct attribute结构,它被用来管理内核sysfs文件的接口(名字,属性,读写函数等)。内核sysfs提供了基本的attribute接口,不同的设备如bus、device在基本attribute的基础上定义了自己的读写函数,sysfs提供了对应的宏来简化属性的操作。请参考<linux/sysfs.h>头文件中。

    struct attribute {  
        const char        *name;
        struct module     *owner;
        mode_t            mode;
    };

    #define __ATTR(_name,_mode,_show,_store) {
        .attr = {.name = __stringify(_name), .mode = _mode },    
        .show    = _show,                    
        .store    = _store,                    
    }

    int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
    int __must_check sysfs_create_dir(struct kobject *kobj);

     

    5. 定义操作函数

    我们看到,sysfs的struct attribute结构本身并不包含读写访问函数,驱动模型的各个部分都会扩展这个结构并定义自己的属性结构来引入各自的操作函数,如 class:(这个结构定义在<linux/device.h>头文件中)。

    struct class_attribute {

    struct attribute attr;

    ssize_t (*show)(struct class *, char * buf);

    ssize_t (*store)(struct class *, const char * buf, size_t count);

    };

    #define CLASS_ATTR(_name, _mode, _show, _store)

    struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store)

     

     

    二、驱动程序详解

     

    1. 定义相关结构体

    首先从大的开始,我们先实现一个框架,我们也就先定义一个kobject结构体,接下来就是定义sysfs_ops和 kobj_type 这两个结构体。

    在kobj_type中将 属性结构体 连接起来。

     

     

    2. 定义属性结构体

    框架搭建好了,我们接下来的任务就是前面我们所说的建立 属性文件夹和属性文件。

     

    3.在init函数中,将kobject注册入内核

     

    4.在exit函数中 删除我们注册的kobject

     

    5.编译测试

     

     

    附上驱动代码:

     

     1 #include <linux/device.h>
     2 #include <linux/module.h>
     3 #include <linux/kernel.h>
     4 #include <linux/init.h>
     5 #include <linux/string.h>
     6 #include <linux/sysfs.h>
     7 #include <linux/stat.h>
     8 
     9 //定义一个名为kobject_test,可以读写的属性
    10 struct attribute test_attr = {
    11     .name = "kobject_test",        //属性名
    12     .mode = S_IRWXUGO,            //属性为可读可写
    13 };
    14 //该kobject只有一个属性
    15 static struct attribute *def_attrs[] = {
    16     &test_attr,
    17     NULL,    
    18 };
    19 
    20 void kobject_test_release(struct kobject *kobject){
    21     printk("kobject_test: kobject_test_release() . 
    ");
    22 }
    23 //读属性的名字
    24 ssize_t kobject_test_show(struct kobject *kobject, struct attribute *attr, char *buf){
    25     printk("call kobject_test_show(). 
    ");        /*调试信息*/
    26     printk("attrname: %s.
    ",attr->name);    //打印属性名字
    27     sprintf(buf,"%s
    ",attr->name);        //将名字方法buf中返回用户空间
    28     return strlen(attr->name) + 2;
    29 }
    30 //写一属性的值
    31 ssize_t kobject_test_store(struct kobject *kobject,struct attribute *attr, const char *buf, size_t count){
    32     printk("call kobject_test_store(). 
    ");    /*调试信息*/
    33     printk("write: %s.
    ",buf);                    //打印属性名字
    34     strcpy(attr->name, buf);                    //写一个属性
    35     return count;
    36 }
    37 
    38 struct sysfs_ops obj_test_sysops = {
    39     .show = kobject_test_show,    //属性读函数
    40     .store = kobject_test_store,    //属性写函数
    41 };
    42 
    43 struct kobj_type ktype={
    44     .release = kobject_test_release,    //释放函数
    45     .sysfs_ops = &obj_test_sysops,        //属性的操作函数
    46     .default_attrs = def_attrs,            //默认属性
    47 };
    48 
    49 struct kobject kobj;        //要添加的kobject结构
    50 static int kobject_test_init(void){
    51     printk("kobject test_init(). 
    ");
    52     kobject_init_and_add(&kobj, &ktype, NULL, "kobject_test");
    53 
    54     return 0;
    55 }
    56 
    57 static int kobject_test_exit(void){
    58     printk("kobject test_exit. 
    ");
    59     kobject_del(&kobj);        //删除kobject
    60     return 0;
    61 }
    62 
    63 module_init(kobject_test_init);
    64 module_exit(kobject_test_exit);
    65 
    66 MODULE_AUTHOR("Lover雪儿");
    67 MODULE_LICENSE("Dual BSD/GPL");
    View Code
  • 相关阅读:
    redhat 7.2 内网安装docker
    使用dockerfile 创建ubuntu ssh镜像
    docker 离线环境安装oracle
    redhat 6.6 、7、Centos7离线安装docker
    用命令行管理aws s3
    Anaconda介绍、安装及使用教程
    python2 编码问题万能钥匙
    从mongo数据库中导出数据的方法
    MongoDB学习第三篇 --- Insert操作
    MongoDB学习笔记(一)-Insert操作
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4298342.html
Copyright © 2020-2023  润新知