Linux驱动结构学习笔记

系统中任一设备都有一个device对象描述,定义在linux/include/linux/device.h
struct device {       
struct klist     klist_children;   //设备列表中的子列表    
struct klist_node   knode_parent;      //表示兄弟节点       
struct klist_node       knode_driver;  //表示驱动节点    
struct klist_node       knode_bus;     //表示总线节点
struct device           *parent;       //指向父设备
struct kobject kobj;        //内嵌的kobject对象
char    bus_id[BUS_ID_SIZE];    //在总线上的位置       
struct device_type      *type;   //设备类型
unsigned     is_registered:1;    //标识该设备是否已经被注册过,仅一位 
unsigned     uevent_suppress:1;  
struct semaphore sem;    //用于同步的信号量
struct bus_type * bus;    //指向总线类型    
struct device_driver *driver;   //所使用的驱动程序 
void   *driver_data;   //驱动的私有数据
void   *platform_data; //平台的特定数据  
struct dev_pm_info    power;
#ifdef CONFIG_NUMA       
int    numa_node;      /* NUMA node this device is close to */
#endif       
u64    *dma_mask;      // dma掩码
u64   coherent_dma_mask;///设备一致性DMA的屏蔽字。
struct list_head   dma_pools;      // dma缓冲池       
struct dma_coherent_mem *dma_mem;  //指向设备所使用的一致性DMA存储器描述符的指针
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;   //       
struct attribute_group **groups;   //附加属性的数组       
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对象的引用计数。

相关推荐