struct device結構體
struct device結構體(2.6.23)
一、定義:
linux/include/linux/device.h
struct device {
struct klist klist_children;
struct klist_node knode_parent; /* node in sibling list */
struct klist_node knode_driver;
struct klist_node knode_bus;
struct device *parent;
struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
unsigned is_registered:1;
unsigned uevent_suppress:1;
struct semaphore sem; /* semaphore to synchronize calls to * its driver.*/
struct bus_type * bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this device */
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device core doesn't touch it */
struct dev_pm_info power;
#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all
hardware supports 64 bit addresses for consistent allocations such descriptors. */
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */
/* arch specific additions */
struct dev_archdata archdata;
spinlock_t devres_lock;
struct list_head devres_head; /* class_device migration path */
struct list_head node;
struct class *class;
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct attribute_group **groups; /* optional groups */
void (*release)(struct device * dev);
};
二、作用:
用於描述設備相關的信息設備之間的層次關係,以及設備與總線、驅動的關係。
三、詳解:
1、struct klist klist_children;
struct klist被定義在linux/include/linux/klist.h中,原型是:
struct klist {
spinlock_t k_lock;
struct list_head k_list;
void (*get)(struct klist_node *);
void (*put)(struct klist_node *);
};
可見它是對struct list_head的擴展,在此它的作用是連接設備列表中的孩子列表。
2、struct klist_node knode_parent; /* node in sibling list */
struct klist_node被定義在linux/include/linux/klist.h,原型是:
struct klist_node {
struct klist * n_klist;
struct list_head n_node;
struct kref n_ref;
struct completion n_removed;
};
在此它的作用是表示它的兄弟節點。
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中,原型是:
struct device_type {
const char *name;
struct attribute_group **groups;
int (*uevent)(struct device *dev, char **envp, int num_envp,char *buffer, int
buffer_size);
void (*release)(struct device *dev);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
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中被實現:
int device_register(struct device *dev){ device_initialize(dev);
return device_add(dev);}
該函數首先是調用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
void device_unregister(struct device * dev){
pr_debug("DEV: Unregistering device. ID = '%s'/n", dev->bus_id);
device_del(dev);
put_device(dev);
}
它會先以KERN_DEBUG級別打印註銷設備的信息,然後才真正刪除設備,減少設備對象的引用計數
。
3、get_device()和put_device()分別是增加和減少設備對象的引用計數。這兩個函數都定義在
:/linux/drivers/base/core.c中。具體是應用在註冊device對象時,device_add()函數會調用
get_device()增加對該device對象的引用計數。在註銷設備對象時,device_unregister()函數
直接調用put_device()函數減少對該device對象的引用計數。