歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux 設備模型淺析之驅動篇

Linux 設備模型,僅僅看理論介紹,比如 LDD3 的第十四章,會感覺太抽象不易理解,而通過閱讀內核代碼就更具體更易理解,所以結合理論介紹和內核代碼閱讀能夠更快速的理解掌握 linux 設備模型。這一序列的文章的目的就是在於此,看這些文章之前最好能夠仔細閱讀
LDD3 的第十四章。大部分 device 和 driver 都被包含在一個特定 bus 中,platform_device 和platform_driver 就是如此,包含在platform_bus_type 中。這裡就以對 platform_bus_type 的調用為主線,淺析 platform_driver 的注冊過程,從而理解 linux 設備模型。platform_bus_type 用於關聯 SOC 的 platform device 和 platform driver,比如在內核 linux-2.6.29 中所有 S3C2410 中的platform device 都保存在 devs.c 中。這裡就以 S3C2410 RTC 的驅動程序 rtc-s3c.c 為例來分析platform_driver_register()例程的調用過程。在文章的最後貼有一張針對本例的 device model 圖片,可在閱讀本文章的時候作為參照。閱讀這篇文章之前,最好先閱讀文章《Linux 設備模型淺析之設備篇》。


一、S3C2410 RTC 的 platform_driver 定義在 drivers/rtc/rtc-s3c.c 中,代碼如下:
static struct platform_driver s3c2410_rtc_driver = {
,probe = s3c_rtc_probe.
,(remove = __devexit_p(s3c_rtc_remove.
,suspend = s3c_rtc_suspend.
,resume = s3c_rtc_resume.
} = driver.
,"name = "s3c2410-rtc.
,owner = THIS_MODULE.
,{
;{
由於 name = "s3c2410-rtc",後面會分析到,它將成為一個目錄的名字,
即/sys/bus/platform/s3c2410-rtc。s3c_rtc_probe ()的調用後面也會講到,其實在之前《Linux 設備
模型淺析之設備篇》中已經分析過了。使用 platform_driver_register()注冊 s3c2410_rtc_driver ,
下面就分析它。
二、platform_driver_register()例程定義在 drivers/base/ platform.c 中,代碼如下:
int platform_driver_register(struct platform_driver *drv)
}
drv->driver.bus = &platform_bus_type; // 設置為 platform_bus_type
if (drv->probe)
drv->driver.probe = platform_drv_probe; // 轉存到 device_driver 中
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)drv->driver.resume = platform_drv_resume;
return driver_register(&drv->driver); // 該例程將 device_driver 注冊到 bus,後面將分析
{
代碼中,
1. 設置成 platform_bus_type 這個很重要,因為 driver 和 device 是通過 bus 聯系在一起的,具
體在本例中是通過 platform_bus_type 中注冊的回調例程和屬性來是實現的,在《Linux 設備模型
淺析之設備篇》中講到的 driver 與 device 的匹配就是通過 platform_bus_type 注冊的回到例程
mach()來完成的。關於 platform_bus_type 的分析請參考《Linux 設備模型淺析之設備篇》。下面
就分析 driver_register()。
三、driver_register()例程定義在 drivers/base/ driver.c 中,代碼如下:
int driver_register(struct device_driver *drv)
}
int ret;
struct device_driver *other;
// 做些判斷
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
/*通過驅動的名字查找 driver,如果找到了,說明已經注冊過,返回錯誤代碼,後面會
分析*/
other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EEXIST;
{
/* 將 driver 加入到 bus 的 kset,並生成些文件夾和鏈接文件,後面會分析 */
ret = bus_add_driver(drv);
if (ret)
return ret;
/* 添加 attribute_group,本例中沒有設置 drv->groups */
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
{
代碼中,
1. 正如該例程的英文注釋所言,大部分工作在 bus_add_driver()例程中完成。
bus_add_driver()例程的作用類似於《Linux 設備模型淺析之設備篇》分析過的
bus_add_device(),只不過後者將 device 添得到 bus 中。下面分析 driver_find()例程。二、driver_find()例程通過驅動所屬 bus 的 driver 容器 drivers_kset 來查找,該例程定義在
drivers/base/ driver.c 中,代碼如下:
struct device_driver *driver_find(const char *name, struct bus_type *bus)
}
struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); // 在 drivers_kset 容器中查找
struct driver_private *priv;
if (k) {
priv = to_driver(k);
return priv->driver; // 返回找到的 driver
{
return NULL;
{
代碼中,
1. 通過 kset_find_obj(bus->p->drivers_kset, name)查找該 driver 的 kobj,其代碼如下,
struct kobject *kset_find_obj(struct kset *kset, const char *name)
}
struct kobject *k;
struct kobject *ret = NULL;
spin_lock(&kset->list_lock);
list_for_each_entry(k, &kset->list, entry) { // 遍歷 kset->list 列表獲取 kobj

Copyright © Linux教程網 All Rights Reserved