driver的初始化,主要是填充了device_driver裡的driver_private這個結構體:
struct driver_private ;
下面一一解釋:
1. kobject和 kset:在linux系統中,最基本的元素就是kobject,而 kobject的集合被稱為kset(kobject set),kobject的parent一定是kset的kobject,且同屬於乙個kset的kobjecs他們的ktype是相同的,均為kset的ktype,這點在kobject初始化的時候被確定,下面會詳細解釋。
2. klist_devices,這個變數代表了該driver可以驅動的device。
3. knode_bus,代表了該driver在bus的klist_driver中的節點。
4. mkobject,代表了該driver在moudles裡的物件例項,在moudle_add_driver時被賦值。
5. devicer_driver 指向自己的driver指標。
driver初始化的流程:
首先,我們會在**裡用moudle_init()巨集來宣告我們的driver的初始化函式,在kernel初始化中,被do_initcalls依次呼叫。
kernel\drivers\base\platform.c platform_driver_register
kernel\drivers\base\driver.c driver_register
kernel\drivers\base\bus.c bus_add_driver
kernel\drivers\base\dd.c driver_attach
kernel\drivers\base\bus.c bus_for_each_dev
kernel\drivers\base\dd.c __device_attach
kernel\drivers\base\base.h driver_match_device
kernel\drivers\base\dd.c driver_probe_device
其中,核心函式是bus_add_driver,下面詳細的分析下:
int bus_add_driver(struct device_driver *drv)
klist_init(&priv->klist_devices, null, null);// 初始化diver支援的devicelist,
priv->driver = drv;
drv->p = priv; // 互指
priv->kobj.kset = bus->p->drivers_kset; // 將driver的kset賦值為bus的kset
error = kobject_init_and_add(&priv->kobj, &driver_ktype, null, /* 此處會初始化driver的kobject,給driver找了個爹,即將parent指標賦值為bus的driver kset,並將其添
加到bus的kset 鍊錶尾部,並呼叫create_dir在sysfs中建立對應的目錄:sys/platform/driver/mydriver
再將state_in_sysfs置為1 */
"%s", drv->name);
if (error)
goto out_unregister;
if (drv->bus->p->drivers_autoprobe)
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); // 將driver新增到bus的 klistdriver裡去
module_add_driver(drv->owner, drv); // 將driver新增到moudles裡,這裡會對mkobject賦值,建立sys/moudles/my/drivers目錄,並在此目錄下建立"platform:mydriver快
// 捷方式,指向 sys/platform/drivers/mydriver",在sys/platform/drivers/mydrive下建立moudles檔案,指向sys/moudles/my/drivers
error = driver_create_file(drv, &driver_attr_uevent); //建立屬性檔案
if (error)
error = driver_add_attrs(bus, drv);
if (error)
if (!drv->suppress_bind_attrs)
}kobject_uevent(&priv->kobj, kobj_add);
return 0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = null;
out_put_bus:
bus_put(bus);
return error;
}driver_attach的**如下,實際就是bus_for_each_dev
int driver_attach(struct device_driver *drv)
在bus_for_each_dev裡會遍歷當前bus的klist_devices ,逐一的呼叫__driver_attach與driver匹配。
static int __driver_attach(struct device *dev, void *data)
static int really_probe(struct device *dev, struct device_driver *drv)
if (dev->bus->probe) else if (drv->probe)
driver_bound(dev); //將device新增到driver的klist_devices末尾,你是我的了~
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = null;
if (ret != -enodev && ret != -enxio)
/** ignore errors returned by ->probe so that the next driver can try
* its luck.
*/ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}這樣,driver和device就繫結了其實總結下來一共就那麼幾件事情:
1. driver的kobject的完善,在sys/platform/drivers下建立了自己的目錄,並將driver新增到 bus的 ksetlist裡,其實就是按個家,找個爹
2. driver和device的匹配,如果成功,則在sys/platform/drivers/mydriver目錄下建立指向sys/platform/dev/mydevice的link檔案,在ys/platform/dev/mydevice建立「driver」指向sys/platform/drivers/mydrive,將driver賦值給device的driver,將device新增到driver的klist末尾,所謂心心相映,找個物件。
3. 在moudles目錄下建立自己的鏈結,完善mkobject,方便系統呼叫。
t b c
linux學習筆記 2
一些常用的基本命令 uname a 檢視核心版本 ls al 顯示所有檔案的屬性 pwd 顯示當前路徑 cd 返回上一次目錄 cd 返回主目錄 date s 設定時間 日期 cal 顯示日曆 cal 2006 bc 計算器具 man info 幫助手冊 locale 顯示當前字型 locale a ...
Linux學習筆記2
1 linux使用者身份與群組記錄的檔案 預設情況下所有系統賬號的資訊都記錄在 etc passwd這個檔案中 個人密碼則記錄在 etc shadow這個檔案中 所有的組名記錄在 etc group中 2 使用ls all檢視目錄下的檔案詳細資訊 例如 rw r r 1 root root 6849...
Linux學習筆記 (2)
閒著無事,就敲起了linux 命令,熟悉一下。記得昨天在書上看到了 find命令的用法,覺得挺神奇的。其中 find 能夠確定檔案的查詢深度 於是 敲了如下命令 建立如下檔案目錄 樹 來試一下 find 的 maxdepth 與 mindepth 當把最大深度設為1時,找到的是 於 father 目...