linux驱动--LDM数据结构

LDM数据结构

总线

总线是设备核处理器之间额通道链路。
管理总线并将其协议输出到设备的硬件实体称为总线控制器。
自身作为设备的总线控制器必须像任何设备那样注册。它是总线上设备的父设备。
结构体struct bus_type

struct bus_type {
       const char      *name;
       const char      *dev_name;
       struct device       *dev_root;
       const struct attribute_group **bus_groups;
       const struct attribute_group **dev_groups;
       const struct attribute_group **drv_groups;
       //每当新设备或驱动程序添加到总线中时调用它。
       int (*match)(struct device *dev, struct device_driver *drv);
       int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
       int (*probe)(struct device *dev);//在新设备或驱动程序添加到总线,并且匹配发生时调用它
       int (*remove)(struct device *dev);//当设备从总线上移除时调用它。
       void (*shutdown)(struct device *dev);
       int (*online)(struct device *dev);
       int (*offline)(struct device *dev);
       int (*suspend)(struct device *dev, pm_message_t state);//总线上的设备进入睡眠模式时
       int (*resume)(struct device *dev);//总线上的设备退出睡眠模式时
       int (*num_vf)(struct device *dev);
       int (*dma_configure)(struct device *dev);
       const struct dev_pm_ops *pm;
       const struct iommu_ops *iommu_ops;
       struct subsys_private *p;
       struct lock_class_key lock_key;
       bool need_parent_lock;
   };

结构体struct kobject

</include/linux/kobject.h>
   struct kobject {
       const char      *name;//object的名称,可使用kobject_set_name函数修改
       struct list_head    entry;
       struct kobject      *parent;//指向kobject父项的指针,用于构建描述对象之间关系的层次结构。
       struct kset     *kset;
       struct kobj_type    *ktype;//描述该对象,kset说明这个对象属于哪套对象
       struct kernfs_node  *sd; /* sysfs directory entry */
       struct kref     kref; //提供kobject上的引用计数
       unsigned int state_initialized:1;
       unsigned int state_in_sysfs:1;
       unsigned int state_add_uevent_sent:1;
       unsigned int state_remove_uevent_sent:1;
       unsigned int uevent_suppress:1;
   };

接口函数

 </include/linux/kobject.h>
    
   kobject *  kobject_create(void);//分配kobject
   void kobject_init(struct kobject *kobj, struct kobj_type *ktype);//初始化kobject
   int kobject_add(struct kobject *kobj, struct kobject *parent,
           const char *fmt, ...);//添加kobject到系统
   void kobject_del(struct kobject *kobj)//将kobject从系统中删除
   void kobject_put(struct kobject *kobj)//与kobject_init和kobject_add过程相反
   //这里创建的kobject无法嵌入到其它结构,是独立存在的,所以用到的地方很少
   struct kobject *  kobject_create_and_add(const char *name,struct kobject *parent);//create与add结合
    
   int kobject_init_and_add(struct kobject *kobj,
                struct kobj_type *ktype, struct kobject *parent,
                const char *fmt, ...);//将kobject初始化后并添加到kobject的层次结构中去。
   /*例
    * 如果 kobject_create_and_add中 kobject 的父项为NULL,那么kobject_add 
    * 将其父项设置为 kset.如果两者均为 NULL,对象将成为顶级 sys 目录的子成员。
    */
   int __init devices_init(void)
   {
       devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
       if (!devices_kset)
           return -ENOMEM;
       //创建/sys/dev
       dev_kobj = kobject_create_and_add("dev", NULL);
       if (!dev_kobj)
           goto dev_kobj_err;
       //创建/sys/dev/block
       sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
       if (!sysfs_dev_block_kobj)
           goto block_kobj_err;
       return 0;
   }

struct kobj_type与sysfs_ops

描述kobject的行为,它将控制在创建和销毁kobject时,以及读取或写入属性时发生的操作。

 </include/linux/kobject.h>
   struct kobj_type {
       void (*release)(struct kobject *kobj);//需要释放对象时由kobject_put函数调用的回调函数。
       const struct sysfs_ops *sysfs_ops;//指向sysfs操作,访问sysfs属性时调用的一组回调函数
       struct attribute **default_attrs;//定义与此kobject关联的默认属性,指向attribute的元素列表   
                                                                 
   的指针
       const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
       const void *(*namespace)(struct kobject *kobj);
       void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
   };
    
   </include/linux/sysfs.h>
   struct sysfs_ops {
       ssize_t (*show)(struct kobject *, struct attribute *, char *);//读取具有该kobj_type的所有kobject的属性时调用它。
       ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);//写入
   };
    
   </include/linux/kobject.h>
   static inline struct kobj_type *get_ktype(struct kobject *kobj)//获取指定koject的kobj_type

内核对象集合(struct kset)

内核对象集合主要将相关的内核对象组合在一起,kset是kobject的集合,换句话说,kset将相关的kobject收集到一个位置,例如所有的块设备

 </include/linux/kobject.h>
   struct kset {
       struct list_head list;//kset中所有kobject的链表
       spinlock_t list_lock;//保护链表访问的自旋锁
       struct kobject kobj;//该集合的基类
       const struct kset_uevent_ops *uevent_ops;//此kset的uevent操作函数集
   } ;

每个注册的kset对应于sysfs目录

 </include/linux/kobject.h>
   struct kset *  kset_create_and_add(const char *name,
                           const struct kset_uevent_ops *u,
                           struct kobject *parent_kobj);//创建kset
   void kset_unregister(struct kset *kset);//删除kset
    
   //例
   static struct kobject foo_kobj;
   //创建/sys/kset_example目录
   example_kset = kset_create_and_add("kset_example",NULL,kernel_kobj);
   //创建/sys/kset_example/foo_name
   foo_kobj.kset = example_kset;
   retval = kobject_init_and_add(&foo_kobj,&foo_ktype,NULL,"foo_name");

属性(struct attribute)
属性是由kobject导出到用户空间的sysfs文件。属性表示可以从用户空间读取、写入或同时具有两者的对象属性。也就是说,嵌入 struct kobject 的每个数据结构都可以公开由 kobject 自身(如果有)提供的默认属性或自定义属性。换话说,属性将内核数据映射到sysfs中。

 </include/linux/sysfs.h>
   struct attribute {
       const char      *name;
       umode_t         mode;
   #ifdef CONFIG_DEBUG_LOCK_ALLOC
       bool            ignore_lockdep:1;
       struct lock_class_key   *key;
       struct lock_class_key   skey;
   #endif
   };

接口函数

 </include/linux/sysfs.h>
    
   int sysfs_create_files(struct kobject *kobj,
                      const struct attribute * const *attr); //从文件系统添加属性
   void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *attr);//删除属性
    
   //示例
   structv d_attr {
       struct attribute attr;
       int value;
   };
   static struct d_attr foo = {
       .attr.name = "foo",
       .attr.mode = "0644",
       .value = 0,
   };
   static struct d_attr bar = {
       .attr.name = "bar",
       .attr.mode = "0644",
       .value = 0,
   };
   sysfs_create_files(mykobj,&foo.attr);
   sysfs_create_files(mykobj,&bar.attr);

属性组(struct attribute_group)
帮助包装器,以便更轻松地管理多个属性

 </include/linux/sysfs.h>
   struct attribute_group {
       const char      *name;
       umode_t         (*is_visible)(struct kobject *,
                             struct attribute *, int);
       umode_t         (*is_bin_visible)(struct kobject *,
                             struct bin_attribute *, int);
       struct attribute    **attrs;
       struct bin_attribute    **bin_attrs;
   };

接口函数

 </include/linux/sysfs.h>
   int  sysfs_create_group(struct kobject *kobj,
                       const struct attribute_group *grp);//向文件系统添加组属性
   void sysfs_remove_group(struct kobject *kobj,
               const struct attribute_group *grp);//向文件系统删除组属性
    
   //示例
   structv d_attr {
       struct attribute attr;
       int value;
   };
   static struct d_attr foo = {
       .attr.name = "foo",
       .attr.mode = "0644",
       .value = 0,
   };
   static struct d_attr bar = {
       .attr.name = "bar",
       .attr.mode = "0644",
       .value = 0,
   };
    
   static struct attribute *attrs [] = {
       &foo.attr,
       &bar.attr,
       NULL,
   };
    
   static struct attribute_group my_attr_group = {
       .attrs = attrs,
   };
    
   sysfs_create_group(mykobj,&my_attr_group);

设备模型和sysfs

sysfs是非持久性虚拟文件系统,它提供系统的全局试图,并通过它们的kobject显示内核对象的层次结构,每个kobject显示为目录和目录中的文件。
/sys目录中的每一个都对应于koject,其中一些作为内核符号导出。

 kernel_kobj //对应于/sys/kernel
   power_kobj //对应于/sys/power
   firmware_kobj //对应于/sys/firmware,导出在drivers/base/firmware.c源文件中
   hypervisor_kobj //对应于/sys/hypervisor,到处在drivers/base/hypervisor.c中
   fs_kobj //对应于/sys/fs,导出在fs/namespace.c文件中

然而,class/、dev/、devices/是在启动期间由内核源代码内drivers/base/core.c中的 devices_init 函数创建的,block在block/genhd,c中创建,bus在drivers/base/bus.c 中被创建为 kset。
kobiect目录被添加到 sysfs (使用 kobject add)时其添加位置取决于 kobiect的父项。如果其父指针已设置,则它将被添加为父目录内的子目录。如果父指针为 NULL则将其添加为 kset-> kobj 内的子目录。如果其父和 kset 字段都未设置,它将映射到sysfs 内的根目录(/sys)
创建/删除现有对象(目录)上的符号链接

 </include/linux/sysfs.h>
   int  sysfs_create_link(struct kobject *kobj, struct kobject *target,
                      const char *name);
   void sysfs_remove_link(struct kobject *kobj, const char *name);

sysfs文件和属性

文件的默认设置是通过 kobject 和 kset 中的 ktype 字段、kobj_type 的 default.attrs 字段提供的。在大多数情况下,默认属性足够了。但有时 ktype 实例可能需要其自己的属性来提供不被更通用的 ktype所共享的数据或功能。
当前接口
目前在 sysfs 中存在接口层。除了创建自己的 ktype 或 kobject 来添加属性外,还可以使用当前存在的设备、驱动程序、总线和类属性。它们的描述如下。
设备属性(struct device_attribute)
除嵌入设备结构中的 kobject 提供的默认属性之外,还可以创建自定义属性。执行止操作使用的结构是struct device_attribute,它只是对标准struct attribute的封装,以及一组用于显示/存储属性值的回调:

 </include/linux/device.h>
    
   struct device_attribute {
       struct attribute    attr;
       ssize_t (*show)(struct device *dev, struct device_attribute *attr,
               char *buf);
       ssize_t (*store)(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count);
   };
   //声明通过DEVICE_ATTR宏完成
   </include/linux/device.h>
   #define DEVICE_ATTR(_name, _mode, _show, _store) \
       struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
    
   </include/linux/device.h>
   int device_create_file(struct device *device,
           const struct device_attribute *entry); //在device中添加属性
   void device_remove_file(struct device *dev,
           const struct device_attribute *attr);在device中删除属性

总线属性(struct bus_attribute)、设备驱动属性(driver_attribute)、类属性

 </include/linux/device.h>
   //2. bus
   struct bus_attribute {
       struct attribute    attr;
       ssize_t (*show)(struct bus_type *bus, char *buf);
       ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
   };
   #define BUS_ATTR(_name, _mode, _show, _store)   \
       struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
   int  bus_create_file(struct bus_type *,
                       struct bus_attribute *);
   void bus_remove_file(struct bus_type *, struct bus_attribute *);
   //3. driver
   struct driver_attribute {
       struct attribute attr;
       ssize_t (*show)(struct device_driver *driver, char *buf);
       ssize_t (*store)(struct device_driver *driver, const char *buf,
                size_t count);
   };
   #define DRIVER_ATTR_RW(_name) \
       struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
   #define DRIVER_ATTR_RO(_name) \
       struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
   #define DRIVER_ATTR_WO(_name) \
       struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
   int  driver_create_file(struct device_driver *driver,
                       const struct driver_attribute *attr);
   void driver_remove_file(struct device_driver *driver,
                      const struct driver_attribute *attr);
   //class
 
  • 18
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值