1. 程式人生 > >struct device 結構

struct device 結構

一、定義:
linux/include/linux/device.h

 407struct device {
408 struct klist klist_children;
409 struct klist_node knode_parent; /* node in sibling list */
410 struct klist_node knode_driver;
411 struct klist_node knode_bus;
412 struct device *
parent
;
413
414 struct kobject kobj;
415 char bus_id[BUS_ID_SIZE]; /* position on parent bus */
416 struct device_type *type;
417 unsigned is_registered:1;
418 unsigned uevent_suppress:1;
419
420 struct semaphore
sem
; /* semaphore to synchronize calls to
421 * its driver.
422 */
423
424 struct bus_type * bus; /* type of bus device is on */
425 struct device_driver *driver; /* which driver has allocated this

426 device */
427 void *driver_data; /* data private to the driver */
428 void *platform_data; /* Platform specific data, device
429 core doesn't touch it */
430 struct dev_pm_info power;
431
432#ifdef CONFIG_NUMA
433 int numa_node; /* NUMA node this device is close to */
434#endif
435 u64 *dma_mask; /* dma mask (if dma'able device) */
436 u64 coherent_dma_mask;/* Like dma_mask, but for
437 alloc_coherent mappings as
438 not all hardware supports
439 64 bit addresses for consistent
440 allocations such descriptors. */
441
442 struct list_head dma_pools; /* dma pools (if dma'ble) */
443
444 struct dma_coherent_mem *dma_mem; /* internal for coherent mem
445 override */
446 /* arch specific additions */
447 struct dev_archdata archdata;
448
449 spinlock_t devres_lock;
450 struct list_head devres_head;
451
452 /* class_device migration path */
453 struct list_head node;
454 struct class *class;
455 dev_t devt; /* dev_t, creates the sysfs "dev" */
456 struct attribute_group **groups; /* optional groups */
457
458 void (*release)(struct device * dev);
459};

二、作用:
用於描述裝置相關的資訊裝置之間的層次關係,以及裝置與匯流排、驅動的關係。
三、詳解:
1、struct klist            klist_children;
struct klist被定義在linux/include/linux/klist.h中,原型是:

可見它是對struct list_head的擴充套件,在此它的作用是連線裝置列表中的孩子列表。
2、struct klist_node       knode_parent; /* node in sibling list */
struct klist_node被定義在linux/include/linux/klist.h,原型是:

在此它的作用是表示它的兄弟節點。
3、struct klist_node       knode_driver;
表示它的驅動節點。
4、struct klist_node       knode_bus;
表示匯流排節點。
5、struct device           *parent;
指向其父裝置。
6、struct kobject kobj;
這裡http://blog.chinaunix.net/u1/55599/showart.php?id=1086478
有對kobject的解釋,此處它是內嵌的一個kobject物件。
7、char    bus_id[BUS_ID_SIZE];
bus_id表示其在父總線上的位置。BUS_ID_SIZE被定義為:
#define KOBJ_NAME_LEN 20 /*linux/include/linux/kobject.h*/
#define BUS_ID_SIZE KOBJ_NAME_LEN /*linux/include/linux/device.h*/

所以表示位置的字串長度不能超過20。
8、struct device_type      *type;
被定義在/linux/include/linux/device.h中,原型是:

device_type結構表示裝置的型別。一個裝置類或者匯流排可以包含不同型別的裝置,例如“分割槽”和“磁碟” , “滑鼠”和“事件” 。device_type就可以標識某個裝置型別和該裝置的特有資訊,它就等同於kobject結構中的kobj_type一樣。如果name資料成員被指定,那麼uevent成員函式就會把它包含在DEVTYPE變數中。
9、unsigned is_registered:1;
標識該裝置是否已經被註冊過。is_registered:1這樣的形式表示is_registered這個變數只有一位。在32位linux系統下,unsigned是4位元組32位,而經過is_registered:1這樣的限制後,變數is_registered只有一位,其取值只能是1或者0,相當於聲明瞭一個boolean型別的變數。在此種用法中,後面指定資料寬度的值只能大於0且小於本身的資料寬度。
10、struct bus_type * bus;
指向所連線匯流排的指標。
11、struct device_driver *driver;
指向被分配到該裝置的裝置驅動。
12、u64 *dma_mask;    /*指向裝置DMA遮蔽字。*/
u64 coherent_dma_mask;/*裝置一致性DMA的遮蔽字。*/
struct list_head dma_pools; /*聚集的DMA緩衝池。*/
struct dma_coherent_mem *dma_mem; /*指向裝置所使用的一致性DMA儲存器描述符的指標*/
13、spinlock_t devres_lock;
定義一個裝置自旋鎖,用於互斥訪問裝置。關於自旋鎖的詳細講解參考:
http://www.deansys.com/doc/ldd3/ch05s05.html

14、void    (*release)(struct device * dev);
釋放裝置描述符的回撥函式。
四、操作:
linux核心系統了一系列完整的對device操作的函式。
1、其中device_register()函式用來將一個新的device物件插入裝置模型。它在linux/drivers/base/core.c中被實現:

該函式首先是呼叫device_initialize()初始化device結構,具體是初始化嵌入的kobject結構dev->kobj,初始化列表中的孩子列表kobj->klist_children,初始化DMA緩衝池dev->dma_pools,初始化自旋鎖dev->devres_lock等。接下來device_add()函式才真正將該device物件dev插入裝置模型中。device_add()函式首先是通過kboject_add()函式將它新增到kobject層次,再把它新增都全域性和兄弟連結串列中,最後新增到其他相關的子系統的驅動程式模型,完成device物件的註冊。
2、device_unregister()完成相反的過程:/linux/drivers/base/core.c
1044void device_unregister(struct device * dev)
1045{
1046 pr_debug("DEV: Unregistering device. ID = '%s'/n", dev->bus_id);
1047 device_del(dev);
1048 put_device(dev);
1049}

它會先以KERN_DEBUG級別列印登出裝置的資訊,然後才真正刪除裝置,減少裝置物件的引用計數。
3、get_device()和put_device()分別是增加和減少裝置物件的引用計數。這兩個函式都定義在:/linux/drivers/base/core.c中。具體是應用在註冊device物件時,device_add()函式會呼叫get_device()增加對該device物件的引用計數。在登出裝置物件時,device_unregister()函式直接呼叫put_device()函式減少對該device物件的引用計數。