1. 程式人生 > >linux驅動註冊過程分析--driver_register(一)

linux驅動註冊過程分析--driver_register(一)

kernel版本3.10.14

driver_register顧名思義,是驅動程式的註冊。但是很少是由我們寫的驅動直接呼叫的,例如framebuffer中呼叫platform_driver_register,i2c中呼叫i2c_add_driver等等函式註冊對應的驅動程式。雖然我們並沒有直接呼叫driver_register,但是最終都是通過driver_register幫我們完成了驅動程式的註冊。所以,瞭解driver_register的註冊過程,對我們理解Linux的裝置驅動有很到的幫助。

我們藉助常用的platform_driver_register開始分析driver_register的呼叫過程。

1.初始化匯流排型別(bus_type),註冊probe等相關函式

在檔案./drivers/base/platform.c中有platform_driver_register原始碼:

[cpp] view plain copy print?
  1. /** 
  2.  * platform_driver_register - register a driver for platform-level devices 
  3.  * @drv: platform driver structure 
  4.  */
  5. int platform_driver_register(struct platform_driver *drv)  
  6. {  
  7.     drv->driver.bus = &platform_bus_type;  
  8.     if (drv->probe)  
  9.         drv->driver.probe = platform_drv_probe;  
  10.     if (drv->remove)  
  11.         drv->driver.remove = platform_drv_remove;  
  12.     if (drv->shutdown)  
  13.         drv->driver.shutdown = platform_drv_shutdown;  
  14.     return
     driver_register(&drv->driver);  
  15. }  
  16. EXPORT_SYMBOL_GPL(platform_driver_register);  
/**
 * platform_driver_register - register a driver for platform-level devices
 * @drv: platform driver structure
 */
int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;
	if (drv->remove)
		drv->driver.remove = platform_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = platform_drv_shutdown;

	return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
上面註冊了相應的probe remove shutdown 等函式後,開始呼叫driver_register

這裡我們需要注意,driver的匯流排型別(bus_type)被初始化為platform_bus_type

[cpp] view plain copy print?
  1. drv->driver.bus = &platform_bus_type;  
drv->driver.bus = &platform_bus_type;
其中platform_bus_type也在檔案./drivers/base/platform.c中有具體定義
[cpp] view plain copy print?
  1. struct bus_type platform_bus_type = {  
  2.     .name       = "platform",  
  3.     .dev_attrs  = platform_dev_attrs,  
  4.     .match      = platform_match,  
  5.     .uevent     = platform_uevent,  
  6.     .pm     = &platform_dev_pm_ops,  
  7. };  
struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_attrs	= platform_dev_attrs,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};
我們是已platform為例講解,所以註冊驅動的匯流排型別是platform的。如果是I2C匯流排呢?

其實也類似,例如在./drivers/i2c/i2c-core.c中有I2C註冊函式i2c_register_driver原始碼(省略部分無關程式碼)

[cpp] view plain copy print?
  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  
  2. {  
  3.     ……  
  4.     driver->driver.owner = owner;  
  5.     driver->driver.bus = &i2c_bus_type;  
  6.      ……  
  7. }  
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
	……
	driver->driver.owner = owner;
	driver->driver.bus = &i2c_bus_type;
     ……
}
res = driver_register(&driver->driver);……return 0;}EXPORT_SYMBOL(i2c_register_driver); 所以,如果註冊的是i2c驅動,那麼匯流排型別初始化為i2c_bus_type,也可以在檔案./drivers/i2c/i2c-core.c中看到其定義 [cpp] view plain copy print?
  1. struct bus_type i2c_bus_type = {  
  2.     .name       = "i2c",  
  3.     .match      = i2c_device_match,  
  4.     .probe      = i2c_device_probe,  
  5.     .remove     = i2c_device_remove,  
  6.     .shutdown   = i2c_device_shutdown,  
  7.     .pm     = &i2c_device_pm_ops,  
  8. };  
struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm_ops,
};

當匯流排型別和probe、remove、shutdown等函式註冊後,就開始呼叫driver_register註冊對應的驅動了。

driver_register原始碼在檔案./drivers/base/driver.c

[cpp] view plain copy print?
  1. /** 
  2.  * driver_register - register driver with bus 
  3.  * @drv: driver to register 
  4.  * 
  5.  * We pass off most of the work to the bus_add_driver() call, 
  6.  * since most of the things we have to do deal with the bus 
  7.  * structures. 
  8.  */
  9. int driver_register(struct device_driver *drv)  
  10. {  
  11.     int ret;  
  12.     struct device_driver *other;  
  13.     BUG_ON(!drv->bus->p);  
  14.     if ((drv->bus->probe && drv->probe) ||  
  15.         (drv->bus->remove && drv->remove) ||  
  16.         (drv->bus->shutdown && drv->shutdown))  
  17.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
  18.             "bus_type methods\n", drv->name);  
  19.     other = driver_find(drv->name, drv->bus);  
  20.     if (other) {  
  21.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
  22.             "aborting...\n", drv->name);  
  23.         return -EBUSY;  
  24.     }  
  25.     ret = bus_add_driver(drv);  
  26.     if (ret)  
  27.         return ret;  
  28.     ret = driver_add_groups(drv, drv->groups);  
  29.     if (ret) {  
  30.         bus_remove_driver(drv);  
  31.         return ret;  
  32.     }  
  33.     kobject_uevent(&drv->p->kobj, KOBJ_ADD);  
  34.     return ret;  
  35. }  
  36. EXPORT_SYMBOL_GPL(driver_register);  
/**
 * driver_register - register driver with bus
 * @drv: driver to register
 *
 * We pass off most of the work to the bus_add_driver() call,
 * since most of the things we have to do deal with the bus
 * structures.
 */
int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	BUG_ON(!drv->bus->p);

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

	other = driver_find(drv->name, drv->bus);
	if (other) {
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}

	ret = bus_add_driver(drv);
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret) {
		bus_remove_driver(drv);
		return ret;
	}
	kobject_uevent(&drv->p->kobj, KOBJ_ADD);

	return ret;
}
EXPORT_SYMBOL_GPL(driver_register);
為了更好閱讀上面的程式碼,我將其化簡如下 [cpp] view plain copy print?
  1. int driver_register(struct device_driver *drv)  
  2.     |  
  3.     |--> driver_find //查詢驅動是否已經裝載
  4.     |--> bus_add_driver//根據匯流排型別新增驅動
  5.     |--> driver_add_groups//將驅動新增到對應組中
  6.     |--> kobject_uevent//註冊uevent事件
int driver_register(struct device_driver *drv)
	|
	|--> driver_find //查詢驅動是否已經裝載
	|--> bus_add_driver//根據匯流排型別新增驅動
	|--> driver_add_groups//將驅動新增到對應組中
	|--> kobject_uevent//註冊uevent事件

2. driver_find分析

在driver_register中呼叫driver_find,driver_find名字很通俗易懂,可以簡單理解為找“驅動”。由於從linux 2.6版本,核心採用裝置驅動模型,所以所謂的“找驅動“還是瞭解一點裝置驅動模型的知識比較好。

在檔案./drivers/base/driver.c中有driver_find原始碼

[cpp] view plain copy print?
  1. /** 
  2.  * driver_find - locate driver on a bus by its name. 
  3.  * @name: name of the driver. 
  4.  * @bus: bus to scan for the driver. 
  5.  * 
  6.  * Call kset_find_obj() to iterate over list of drivers on 
  7.  * a bus to find driver by name. Return driver if found. 
  8.  * 
  9.  * This routine provides no locking to prevent the driver it returns 
  10.  * from being unregistered or unloaded while the caller is using it. 
  11.  * The caller is responsible for preventing this. 
  12.  */
  13. struct device_driver *driver_find(constchar *name, struct bus_type *bus)  
  14. {  
  15.     struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  
  16.     struct driver_private *priv;  
  17.     if (k) {  
  18.         /* Drop reference added by kset_find_obj() */
  19.         kobject_put(k);  
  20.         priv = to_driver(k);  
  21.         return priv->driver;  
  22.     }  
  23.     return NULL;  
  24. }  
  25. EXPORT_SYMBOL_GPL(driver_find);  
/**
 * driver_find - locate driver on a bus by its name.
 * @name: name of the driver.
 * @bus: bus to scan for the driver.
 *
 * Call kset_find_obj() to iterate over list of drivers on
 * a bus to find driver by name. Return driver if found.
 *
 * This routine provides no locking to prevent the driver it returns
 * from being unregistered or unloaded while the caller is using it.
 * The caller is responsible for preventing this.
 */
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
	struct driver_private *priv;

	if (k) {
		/* Drop reference added by kset_find_obj() */
		kobject_put(k);
		priv = to_driver(k);
		return priv->driver;
	}
	return NULL;
}
EXPORT_SYMBOL_GPL(driver_find);

我們注意通過註釋和程式碼知道,driver_find 通過我們給定的name在某bus中尋找驅動。這個比較好理解,就像上學的時候,老師XX知道某個學生的名字(name),然後去他所在的班級(bus)找這個學生。如果找到過(一般沒好事TT),就把學生叫出來好好教育一番....。那麼driver_find找了所謂的驅動會怎樣呢?我們觀察driver_find的返回值,你會發現,這裡返回的是指標,也就是說driver_find是一個指標函式嘍。指標的型別是struct device_driver型別的。

struct device_driver 在檔案 include/linux/device.h中定義

[cpp] view plain copy print?
  1. /** 
  2.  * struct device_driver - The basic device driver structure 
  3.  * @name:   Name of the device driver. 
  4.  * @bus:    The bus which the device of this driver belongs to. 
  5.  * @owner:  The module owner. 
  6.  * @mod_name:   Used for built-in modules. 
  7.  * @suppress_bind_attrs: Disables bind/unbind via sysfs. 
  8.  * @of_match_table: The open firmware table. 
  9.  * @acpi_match_table: The ACPI match table. 
  10.  * @probe:  Called to query the existence of a specific device, 
  11.  *      whether this driver can work with it, and bind the driver 
  12.  *      to a specific device. 
  13.  * @remove: Called when the device is removed from the system to 
  14.  *      unbind a device from this driver. 
  15.  * @shutdown:   Called at shut-down time to quiesce the device. 
  16.  * @suspend:    Called to put the device to sleep mode. Usually to a 
  17.  *      low power state. 
  18.  * @resume: Called to bring a device from sleep mode. 
  19.  * @groups: Default attributes that get created by the driver core 
  20.  *      automatically. 
  21.  * @pm:     Power management operations of the device which matched 
  22.  *      this driver. 
  23.  * @p:      Driver core's private data, no one other than the driver 
  24.  *      core can touch this. 
  25.  * 
  26.  * The device driver-model tracks all of the drivers known to the system. 
  27.  * The main reason for this tracking is to enable the driver core to match 
  28.  * up drivers with new devices. Once drivers are known objects within the 
  29.  * system, however, a number of other things become possible. Device drivers 
  30.  * can export information and configuration variables that are independent 
  31.  * of any specific device. 
  32.  */
  33. struct device_driver {  
  34.     constchar      *name;  
  35.     struct bus_type     *bus;  
  36.     struct module       *owner;  
  37.     constchar      *mod_name;  /* used for built-in modules */
  38.     bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */
  39.     conststruct of_device_id   *of_match_table;  
  40.     conststruct acpi_device_id *acpi_match_table;  
  41.     int (*probe) (struct device *dev);  
  42.     int (*remove) (struct device *dev);  
  43.     void (*shutdown) (struct device *dev);  
  44.     int (*suspend) (struct device *dev, pm_message_t state);  
  45.     int (*resume) (struct device *dev);  
  46.     conststruct attribute_group **groups;  
  47.     conststruct dev_pm_ops *pm;  
  48.     struct driver_private *p;  
  49. };  
/**
 * struct device_driver - The basic device driver structure
 * @name:	Name of the device driver.
 * @bus:	The bus which the device of this driver belongs to.
 * @owner:	The module owner.
 * @mod_name:	Used for built-in modules.
 * @suppress_bind_attrs: Disables bind/unbind via sysfs.
 * @of_match_table: The open firmware table.
 * @acpi_match_table: The ACPI match table.
 * @probe:	Called to query the existence of a specific device,
 *		whether this driver can work with it, and bind the driver
 *		to a specific device.
 * @remove:	Called when the device is removed from the system to
 *		unbind a device from this driver.
 * @shutdown:	Called at shut-down time to quiesce the device.
 * @suspend:	Called to put the device to sleep mode. Usually to a
 *		low power state.
 * @resume:	Called to bring a device from sleep mode.
 * @groups:	Default attributes that get created by the driver core
 *		automatically.
 * @pm:		Power management operations of the device which matched
 *		this driver.
 * @p:		Driver core's private data, no one other than the driver
 *		core can touch this.
 *
 * The device driver-model tracks all of the drivers known to the system.
 * The main reason for this tracking is to enable the driver core to match
 * up drivers with new devices. Once drivers are known objects within the
 * system, however, a number of other things become possible. Device drivers
 * can export information and configuration variables that are independent
 * of any specific device.
 */
struct device_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;
	const struct acpi_device_id	*acpi_match_table;

	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 attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};
這個結構體裡面包含了裝置驅動的重要資訊,例如名字(name)、匯流排型別(bus)、所述模組(owner)和一些用於回撥的函式指標(probe,remove,suspend...)。總而言之,得到此指標就像得到了驅動,就像得民心者得天下閉嘴....

/*******************************************************************************************************************************

下面涉及到裝置驅動,這裡只是簡單提一下,一時看不懂很正常。如果有時間還想把裝置驅動專門寫幾篇博文

*******************************************************************************************************************************/

那麼問題來了,driver_find到底是如何通過name在bus中尋找驅動呢。其實就是通過下面的程式碼實現的

[cpp] view plain copy print?
  1. struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  
struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
其中kset_find_obj貌似很高階的樣子,這又得談到linux的裝置模型了。linux2.6為了更好的管理,加入了一系列”面向物件“概念,說簡單點就是更好的管理資源。例如一些資源佔用了記憶體空間,但是卻沒有人去使用,這種資源其實是可以從記憶體中被釋放的。

所以實現了基本的面向物件管理機制,是構成Linux2.6裝置模型的核心結構。它與sysfs檔案系統緊密相連,在核心中註冊的每個kobject物件對應sysfs檔案系統中的一個目錄。類似於C++中的基類,Kobject常被嵌入於其他型別(即:容器)中。如bus,devices,drivers都是典型的容器。這些容器通過kobject連線起來,形成了一個樹狀結構。Bus:在核心中註冊的每條匯流排在該目錄下對應一個子目錄,如: i2c platform spi ide pci scsi等等 其中每個匯流排目錄內又包含兩個子目錄:devices和drivers ,devices目錄包含了在整個系統中發現的屬於該匯流排型別的裝置,drivers目錄包含了註冊到該匯流排。其實說這麼多,就是想讓讀者瞭解一點,我們的driver和bus型別、Kobject,kset等有莫大的關聯。至於具體的原理,大家可以自己找一些裝置驅動的資料看看。這裡就不詳細說明了。

 在檔案./lib/kobject.c  檔案中有kset_find_obj函式的原始碼

[cpp] view plain copy print?
  1.  * kset_find_obj - search for object in kset.  
  2.  * @kset: kset we're looking in.  
  3.  * @name: object's name.  
  4.  *  
  5.  * Lock kset via @kset->subsys, and iterate over @kset->list,  
  6.  * looking for a matching kobject. If matching object is found  
  7.  * take a reference and return the object.  
  8.  */  
  9. struct kobject *kset_find_obj(struct kset *kset, constchar *name)  
  10. {  
  11.     struct kobject *k;  
  12.     struct kobject *ret = NULL;  
  13.     spin_lock(&kset->list_lock);  
  14.     list_for_each_entry(k, &kset->list, entry) {  
  15.         if (kobject_name(k) && !strcmp(kobject_name(k), name)) {  
  16.             ret = kobject_get_unless_zero(k);  
  17.             break;  
  18.         }  
  19.     }  
  20.     spin_unlock(&kset->list_lock);  
  21.     return ret;  
  22. }  
 * kset_find_obj - search for object in kset.
 * @kset: kset we're looking in.
 * @name: object's name.
 *
 * Lock kset via @kset->subsys, and iterate over @kset->list,
 * looking for a matching kobject. If matching object is found
 * take a reference and return the object.
 */
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) {
		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
			ret = kobject_get_unless_zero(k);
			break;
		}
	}

	spin_unlock(&kset->list_lock);
	return ret;
}
這裡面涉及到了一個很常用很的巨集函式list_for_each_entry,不知道的童鞋可以點選這裡。kset_find_obj通過迴圈操作,,根據我們給的名字name在指定的bus中迴圈對比,檢視是否有相同的名字name(這個name存放在kobj中)。其實這就是一個迴圈連結串列的遍歷過程,kset和kobj裡面都有連結串列指標next和prev。kset是a set of kobjects,kobj是kernel object,所以kset是一系列的kobj的組合。其中kset,核心中的解釋是struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.那麼這裡有個重要的belonging to啦,也就是現在分詞做定語尷尬。哈哈,belonging to a specific subsystem說的是kset(一系列kobjs)屬於特定的子系統。所以,初學者我們可以這麼思考,一個kobj應該是屬於某個kset(或者說kobj在kset迴圈連結串列中),kset又是屬於某個subsystem的。所以,我們要通過name去尋找驅動,就必須要知道bustype,然後得到kset,最後得到kobj才能去對比name是否相同。這時我們回頭看看呼叫driver_find(drv->name, drv->bus);時,不就給了drv->bus,然後通過bus->p->drivers_kset得到了kset。

總結driver_find過程如下:

1. driver_find,拿到了drv->name和drv->bus開始找驅動

2. kset_find_obj 通過driver_find傳遞的bus->p->drivers_kset,利用list_for_each_entry遍歷kset迴圈連結串列。(kset結構體中有迴圈連結串列指標next和prev)

3. 遍歷迴圈連結串列中每一個kobj中的成員變數name

4. 通過strcmp(kobject_name(k), name)比較drv->name 和kobj中的name,如果有相同則表示查詢成功

5. return :如果找到,則返回device_driver的指標,如果沒有找到則返回了NULL。

為了能更好的說明driver_find,我用下面的圖示意一下。


通過下面driver_register的程式碼可以看出呼叫driver_find的作用,

[cpp] view plain copy print?
  1. other = driver_find(drv->name, drv->bus);  
  2. if (other) {  
  3.     printk(KERN_ERR "Error: Driver '%s' is already registered, "
  4.         "aborting...\n", drv->name);  
  5.     return -EBUSY;  
  6. }  
	other = driver_find(drv->name, drv->bus);
	if (other) {
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}
通過判斷driver_find的返回值other,如果if(other)條件成立,說明other不是NULL,也就是說driver_find查詢成功。但driver_register是註冊驅動程式,如果驅動已經註冊過,就不需要再次註冊了。如果已經註冊,那麼直接return -EBUSY;後面的操作就不需要進行了。

所以driver_register呼叫driver_find是為了檢驗驅動是否已經被註冊,防止重複註冊。