struct device結構體

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對象的引用計數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章