现在的位置: 首页 > 综合 > 正文

device_driver结构体

2012年03月27日 ⁄ 综合 ⁄ 共 3898字 ⁄ 字号 评论关闭

一、定义:

struct device_driver结构体被定义在/include/linux/device.h,原型是:

 124struct device_driver {
 125        const char              * name;
 126        struct bus_type         * bus;
 127
 128        struct kobject          kobj;
 129        struct klist            klist_devices;
 130        struct klist_node       knode_bus;
 131
 132        struct module           * owner;
 133        const char              * mod_name;     /* used for built-in modules */
 134        struct module_kobject   * mkobj;
 135
 136        int     (*probe)        (struct device * dev);
 137        int     (*remove)       (struct device * dev);
 138        void    (*shutdown)     (struct device * dev);
 139        int     (*suspend)      (struct device * dev, pm_message_t state);
 140        int     (*resume)       (struct device * dev);
 141};

二、作用:
描述设备驱动程序模型中的驱动程序。
三、各字段详解:
1char* name; 
设备驱动程序的名称。在调用driver_register()往设备驱动程序模型中插入一个新的device_driver对象时,
driver_register()函数会调用bus_add_driver()函数,bus_add_driver()调用kobject_set_name()函数将

name
赋给drv>kobj.name或者drv->kobj.k_name 注:drv为要调用driver_register()注册的device_driver类型的对象。 2struct bus_type *bus; 指向总线描述符的指针,总线连接所支持的设备。此处我的理解是连接的是所有可使用该驱动程序驱动的
设备。
3struct kobject kobj; 内嵌的kobject结构。最主要的作用还是使用它包含的引用计数器kref记录device_driver对象的使用情况。 4struct module *owner; const char *mod_name; struct module_kobject *mkobj;
表示实现设备驱动程序的模块。也就是在该驱动的实现中,如果使用了模块,那么该域就指向你所写的模
块,并使用
mod_name域指向模块名。如果没有使用模块,那该域就为空。还有该结构中的

module_kobject
类型的mkobj也是与owner有关的域。
5、
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);

这五个回调函数用于处理热插拔、即插即用和电源管理。

      当总线设备驱动程序发现一个可能有它处理的设备时就会调用probe方法,相应的函数将会探测硬件,
从而对该设备进行更进一步的检查。如果该
device_driver对象的pribe()
方法的返回值是一个负数,那就意
味这该驱动不能邦定到此设备上,那么就要释放所有为该
device_driver
对象分配的资源。
  当移走一个可热插拔的设备时驱动程序会调用remove
方法,而驱动程序本身被卸载时,它所处理的每
个设备也会调用
remove方法。
当内核必须更改设备的供电状态时,设备驱动会调用shutdownsuspendresume
三个方法。其中
shutdown方法会停止对设备供电。suspend方法是将设备切换到低功耗状态,此方法中的state
参数即要
设置的状态,
pm_message_t被定义在linux/include/linux/pm.h
中,
typedef struct pm_message {
int event;
}pm_message_t;

 

可取的状态有:
#define PM_EVENT_ON 0
/*
驱动器恢复工作,开始相应硬盘和软件请求*/

#define PM_EVENT_FREEZE 1
/*
停止对设备的操作以便保存一致的映象,但是不能再进入低功耗状态,也不能发出唤醒事件*/

#define PM_EVENT_SUSPEND 2 /*为即将到来的系统状态进入低功耗状态,在适当的时候可以唤醒*/

#define PM_EVENT_PRETHAW 3 /*为系统从一个较早的PM_EVENT_FREEZE保存的映象中恢复过来 做准备*/
更多关于 pm_message_t的解释参见http://lxr.linux.no/linux/include/linux/pm.h
由低功耗状态唤醒设备就要调用resume方法。

四、操作函数:

1driver_register()函数:/linux/drivers/base/driver.c
 153int driver_register(struct device_driver * drv)
 154{
 155        if ((drv->bus->probe && drv->probe) ||
 156            (drv->bus->remove && drv->remove) ||
 157            (drv->bus->shutdown && drv->shutdown)) {
 158                printk(KERN_WARNING "Driver '%s' needs updating - please use 
bus_type methods/n",
drv->name);
159 } 160 klist_init(&drv->klist_devices, NULL, NULL); 161 return bus_add_driver(drv); 162}

函数首先是检查device_driver类型的drv对象和其bus域的回调函数是否已经被赋值,如果为空,则打印警告。
核心的注册是调用
bus_add_driver()函数实现。bus_add_driver()函数中,首先是检查drv->bus
,如果为空
可立即返回
EINVAL(无效的变量),注册失败,可见bus域必须提前初始化好才行。接下来是对kobj
域进行初始
化,检查
bus域等。最后调用add_bind_files()函数(实际上是由add_bind_files()函数调用driver_create_file()

)sys
文件系统下为其创建一个新的目录。

2driver_register()函数:/linux/drivers/base/driver.c

 

/linux/drivers/base/driver.c
 171void driver_unregister(struct device_driver * drv)
 172{
 173        bus_remove_driver(drv);
 174}
/linux/drivers/base/bus.c
 665void bus_remove_driver(struct device_driver * drv)
 666{
 667        if (!drv->bus)
 668                return;
 669
 670        remove_bind_files(drv);
 671        driver_remove_attrs(drv->bus, drv);
 672        klist_remove(&drv->knode_bus);
 673        pr_debug("bus %s: remove driver %s/n", drv->bus->name, drv->name);
 674        driver_detach(drv);
 675        module_remove_driver(drv);
 676        kobject_unregister(&drv->kobj);
 677        put_bus(drv->bus);
 678}

 

bus_remove_driver()函数中首先是检查要卸载的device_driver类型的对象drvbus域,如果为空则返回。
此种情况会发生在调用
driver_register()函数注册drv时没有检查返回值,注册失败,但程序依然向下运行,到

driver_unregister()
时就会到688行处返回。接下来会删除在调用driver_register()函数注册时在sys文件系统中
创建的目录,然后删除
drv对象的属性,(属性是记录在文件中的,删除属性其实是删除记录drv->bus
属性的文
),删除驱动模块,减少对drv->bus的引用计数等。

3get_driver()put_driver()函数:
分别是增加和减少对该device_drvier类型的对象的引用计数。
4int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
;

void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr);
分别是在sys文件系统中为device_driver对象创建和删除目录。
五、参考:
Understanding the linux kernel
http://lxr.linux.no/linux/Documentation/driver-model/driver.txt

抱歉!评论已关闭.