Linux驱动学习笔记(二)

Kobject相关

kobject描述结构体:

struct kobject {

     const char         *name;

     struct list_head   entry;

     struct kobject         *parent;//指向父对象

     struct kset        *kset;

     struct kobj_type   *ktype;

     struct sysfs_dirent    *sd;

     struct kref        kref;//对象引用计数

     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;

};

初始化kobject结构体:

voidkobject_init(struct kobject *kobj, struct kobj_type *ktype);

将kobject对象注册到linux系统:

intkobject_add(struct kobject *kobj, struct kobject *parent,const char *fmt, ...);

初始化kobject并注册到linux系统:

int kobject_init_and_add(structkobject *kobj,struct kobj_type *ktype,

struct kobject *parent,const char *fmt, ...);

删除kobject对象:

voidkobject_del(struct kobject *kobj);

将kobject对象引用计数加1,并返回该对象指针:

struct kobject*kobject_get(struct kobject *kobj);

将kobject对象引用计数减1,减到0则调用release进行释放对象:

voidkobject_put(struct kobject *kobj);

kobject对象的一些属性:

struct kobj_type{

     void (*release)(struct kobject *kobj);

     const struct sysfs_ops *sysfs_ops;

     struct attribute **default_attrs;

     const struct kobj_ns_type_operations*(*child_ns_type)(struct kobject *kobj);

     const void *(*namespace)(struct kobject*kobj);

};

Kobject目录下的一个文件:(name为文件名)

structkobj_attribute {

     struct attribute attr;

     ssize_t (*show)(struct kobject *kobj,struct kobj_attribute *attr,char *buf);

     ssize_t (*store)(struct kobject *kobj,struct kobj_attribute *attr,

               const char *buf, size_t count);

};

当用户读属性文件时调用show函数,属性存入buffer返回给用户:

ssize_t(*show)(struct kobject *,struct attribute *,char *);

当用户写属性文件时调用store函数,存储用户传入的属性:

ssize_t (*store)(structkobject *,struct attribute *,const char *,size_t);

相同类型kobject的集合kset,在sysfs中体现为一目录:

struct kset {

     struct list_head list;

     spinlock_t list_lock;

     struct kobject kobj;

     const struct kset_uevent_ops *uevent_ops;

};

内核中注册kset:

intkset_register(struct kset *kset);

内核中注销kset:

voidkset_unregister(struct kset *kset);

 

热插拔事件

在linux系统中,当系统配置发生变化时:如添加kset到系统;移动kobject,一个通知会从内核空间发送到用户空间,这就是热插拔事件。会导致用户空间中相应的处理程序(udev,mdev)被调用,会加载驱动程序,创建设备节点来响应热插拔事件。

操作集合kset_uevent_ops:kobject和kset状态发生变化时调用三个函数

structkset_uevent_ops {

     //决定是否将事件传递到用户空间

     int (* const filter)(struct kset *kset,struct kobject *kobj);

     //用于将字符串传递给用户空间的热插拔处理程序  

const char *(* const name)(struct kset *kset, struct kobject *kobj);

     //将用户空间需要的参数添加到环境变量中

int (* const uevent)(struct kset *kset, struct kobject *kobj,

              struct kobj_uevent_env *env);

};

 

总线

总线是处理器和设备之间的通道,在设备模型中,所有的设备都是通过总线相连,甚至是内部的虚拟“platform”总线。在linux设备模型中,总线由struct bus_type结构表示,定义在<linux/device.h>。

struct bus_type {

     const char         *name;

     struct bus_attribute   *bus_attrs;

     struct device_attribute *dev_attrs;

     struct driver_attribute *drv_attrs;

     int (*match)(struct device *dev, structdevice_driver *drv);

     int (*uevent)(struct device *dev, structkobj_uevent_env *env);

     int (*probe)(struct device *dev);

     int (*remove)(struct device *dev);

     void (*shutdown)(struct device *dev);

     int (*suspend)(struct device *dev,pm_message_t state);

     int (*resume)(struct device *dev);

     const struct dev_pm_ops *pm;

     struct iommu_ops *iommu_ops;

     struct subsys_private *p;

};

总线注册使用:

bus_register(structbusy_type *bus);新添加的总线会出现在/sys/bus下

总线删除使用:

bus_unregister(structbusy_type *bus);

匹配设备和驱动程序:

int (*match)(structdevice *dev,struct device_driver *drv);

当一个新设备或者驱动被添加到这个总线时,该方法被调用。用于判断指定的驱动程序是否能处理指定的设备。可以返回非零值。

 

总线方法:

int (*uevent)(structdevice *dev,char **envp,int num_envp,char *buffer,int buffer_size);在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量。

总线属性:

在structbus_attribute结构中描述总线属性。

structbus_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);

};

BUS_ATTR(_name,_mode, _show, _store)。

创建总线属性文件:

intbus_create_file(struct bus_type * bus,structbus_attribute *attr);

删除总线属性文件:

voidbus_remove_file(struct bus_type *    bus,structbus_attribute *attr);

 

设备

Linux中设备由struct device结构体描述

注册设备:

intdevice_register(struct device *dev);

删除设备:

void device_unregister(structdevice *dev);

设备属性:(由结构体struct device_attribute描述)

structdevice_attribute {

     struct attribute   attr;

     ssize_t (*show)(struct device *dev, structdevice_attribute *attr,char *buf);

     ssize_t (*store)(struct device *dev, structdevice_attribute *attr,

const char *buf, size_t count);

};

DEVICE_ATTR(_name,_mode, _show, _store)。

创建设备属性文件:

int device_create_file(structdevice *device,const struct device_attribute *entry);

删除设备属性文件:

void device_remove_file(structdevice *dev,const struct device_attribute *attr);

 

驱动

总线中的驱动描述:

structdevice_driver {

     const char         *name;

     struct bus_type        *bus;

     struct module      *owner;

     const char         *mod_name;    /* used for built-in modules */

     bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */

     const struct of_device_id   *of_match_table;

     int (*probe) (struct device *dev);

     int (*remove) (struct device *dev);

     void (*shutdown) (struct device *dev);

     int (*suspend) (struct device *dev, pm_message_tstate);

     int (*resume) (struct device *dev);

     const struct attribute_group **groups;

     const struct dev_pm_ops *pm;

     struct driver_private *p;

};

总线驱动注册:

intdriver_register(struct device_driver *drv);

总线驱动注销:

voiddriver_unregister(struct device_driver *drv);

驱动属性:

structdriver_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);

};

DRIVER_ATTR(_name,_mode, _show, _store)。

创建驱动属性文件:

intdriver_create_file(struct device_driver *driver,const struct driver_attribute*attr);

删除驱动属性文件:

voiddriver_remove_file(struct device_driver *driver,const struct driver_attribute*attr);

 

platform平台总线

设备描述结构体:platform_device

structplatform_device {

     const char    *name;/*设备名*/

     int      id;/*设备编号,配合设备名使用*/

     struct device dev;

     u32      num_resources;

     struct resource *resource;/*设备资源*/

     const struct platform_device_id  *id_entry;

     /* MFD cell pointer */

     struct mfd_cell *mfd_cell;

     /* arch specific additions */

     struct pdev_archdata   archdata;

};

platform_device的分配:

structplatform_device *platform_device_alloc(const char *name, int id);

name设备名,id设备id,一般为-1.

添加平台设备:

intplatform_device_add(struct platform_device *pdev);

获取资源:

struct resource*platform_get_resource(struct platform_device *, unsigned int, unsigned int);dev资源所属的设备;type获取的资源类型;num获取的资源数

 

注册和注销设备:

intplatform_device_register(struct platform_device *);

voidplatform_device_unregister(struct platform_device *);

 

设备驱动结构体:platform_driver

structplatform_driver {

     int (*probe)(struct platform_device *);

     int (*remove)(struct platform_device *);

     void (*shutdown)(struct platform_device *);

     int (*suspend)(struct platform_device *,pm_message_t state);

     int (*resume)(struct platform_device *);

     struct device_driver driver;

     const struct platform_device_id *id_table;

};

 

注册和注销驱动程序:

intplatform_driver_register(struct platform_driver *);

voidplatform_driver_unregister(struct platform_driver *);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值