Linux設備模型--驅動

http://blog.chinaunix.net/uid-20672257-id-3147001.html


linux中每個設備驅動由一個struct device_driver描述:

  1. struct device_driver {  
  2.     const char      *name;               //設備驅動程序的名稱  
  3.     struct bus_type     *bus;                //該驅動所管理的設備掛接的總線類型  
  4.     struct module       *owner;  
  5.     const char      *mod_name;  /* used for built-in modules */  
  6.     int (*probe) (struct device *dev);  
  7.     int (*remove) (struct device *dev);  
  8.     void (*shutdown) (struct device *dev);  
  9.     int (*suspend) (struct device *dev, pm_message_t state);  
  10.     int (*resume) (struct device *dev);  
  11.     struct attribute_group **groups;  
  12.     struct dev_pm_ops *pm;  
  13.     struct driver_private *p;  
  14. };  
  15. struct driver_private {  
  16.     struct kobject kobj;  
  17.     struct klist klist_devices;               //該驅動所管理的設備鏈表頭  
  18.     struct klist_node knode_bus;              //掛入總線鏈表中的指針  
  19.     struct module_kobject *mkobj;  
  20.     struct device_driver *driver;  
  21. };  
  22. struct driver_attribute {  
  23.     struct attribute attr;  
  24.     ssize_t (*show)(struct device_driver *driver, char *buf);  
  25.     ssize_t (*store)(struct device_driver *driver, const char *buf,  
  26.              size_t count);  
  27. };  

可以看出device結構體中也包含了一個kobject對象和連接設備的鏈表。

當設備從系統總刪除是remove被調用。

當系統關機的時候shutdown被調用。

註冊一個設備驅動
int driver_register(struct driver *drv)
刪除一個設備驅動
void  driver_unregister(struct driver *drv)


創建屬性
int driver_create_file(struct driver *drv,struct driver_attribute *attr)
刪除屬性
int driver_remove_file(struct driver *drv,struct driver_attribute *attr)

struct device_driver中有個int (*probe) (struct device *dev)函數,它什麼時候調用呢?
device_driver中name指向驅動的名字,前面的struct device中也有一個名爲bus_id的字符數組。查看一下,struct bus_type中有一個match函數,這個是幹什麼用的呢。設備有了驅動纔可以工作,只有驅動沒有設備也是不行,驅動和設備需要關聯上,這就需要這個match函數。驅動和設備是通過name來管理的,所以在總線驅動match函數中要比較device的bus_id和driver中的name是否相等,什麼時候比較?只要往總線添加設備或驅動時,總線都會把調用match函數對新添加的設備或驅動中名字與總線中已經註冊的驅動或設備的名字一一比較。如果有相等,就說明驅動和設備互相找到了,這時device_driver中的probe函數就被調用。

添加設備驅動例子,添加到前面創建的my_bus總線上:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

extern struct bus_type my_bus_type;

static int my_probe(struct device *dev)
{
    printk("Driver found device which my driver can handle!\n");
    return 0;
}

static int my_remove(struct device *dev)
{
    printk("Driver found device unpluged!\n");
    return 0;
}

struct device_driver my_driver = {
.name = "my_dev",
.bus = &my_bus_type,
.probe = my_probe,
        .remove = my_remove,
};

/*
 * Export a simple attribute.
 */
static ssize_t mydriver_show(struct device_driver *driver, char *buf)
{
return sprintf(buf, "%s\n", "This is my driver!");
}

static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);

static int __init my_driver_init(void)
{
int ret = 0;
        
        /*註冊驅動*/
driver_register(&my_driver);
/*創建屬性文件*/
driver_create_file(&my_driver, &driver_attr_drv);
return ret;

}

static void my_driver_exit(void)
{
driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

創建一個名爲“bus_dev”的驅動,並將bus成員指向第一步創建的my_bus_type總線

測試結果:

加載驅動將會打印:Driver found device which my driver can handle!
查看/sys/bus/my_bus/driver
ls /sys/bus/my_bus/driver
my_dev


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章