嵌入式linux平台设备驱动(设备驱动模型)开发之linux内核中的设备驱动

时间:2022-04-05 10:29:46

linux 内核中的设备驱动

  在linux的内核中,所有外部设备都有与之相对应的设备驱动,设备驱动都调用struct device_driver 来表示,所有的设备驱动都被加载到相应的总线的设备驱动列表之中,即usb结构体struct klist klist_driver 成员中,struct device_driver的主要成员如下: 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;


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

struct device_private {
struct klist klist_children;
struct klist_node knode_parent;
struct klist_node knode_driver;
struct klist_node knode_bus;
void *driver_data;
struct device *device;
};

其中主要成员介绍: bus:代表设备驱动所在的总线 probe:设备探测函数,在设备和设备驱动进行绑定时调用,在设备驱动代码中实现。 klist_devices:表示所有使用该设备驱动的设备链表,所有使用该设备驱动使用device都被挂在klist_devices的链表之中,在注册设备或则设备驱动时,如果匹配成功,则会进行相应的操作。 struct klist_knode knode_bus:device_driver通过该成员把device_driver连接到它所在设备驱动链表之中,klist_drivers链表里面挂载所有挂载该总线上设备驱动。
linux 内核重新定义一些结构体来表示那些挂载总线上的设备驱动。例子如下: 平台总线上的设备驱动用结构体platform_driver表示,挂载在usb总线上设备驱动用结构体struct usb_driver表示。其中usb_driver和platform_driver都包含了结构体struct device_driver。可以理解为platform_driver为struct device_driver的子类,其中platform_driver的结构体如下: struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};


platform_driver  结构体包含了结构体struct device_driver,并且platform_driver  还重新定义了自己的探测函数,在进行设备和设备驱动注册时,内核通过调用设备驱动提供的探测函数,最终执行platform_driver  中的探测函数,该功能是通过platform_driver_register来实现:
int platform_driver_register(struct platform_driver *drv) {   if(drv->probe)        drv->driver.probe = platform_drv_probe; }
static int platform_drv_probe(struct device *_dev) {     struct platform_driver *drv = to_platform_driver(_dev->driver);     struct platform_device *dev = to_platform_device(_dev);         return drv->probe(dev); }

函数调用过程详解:在设备和设备驱动进行注册时,在设备与设备驱动进行匹配成功之后,执行设备驱动的probe函数,执行platform_drv_probe函数,在platform_drv_probes 函数 获取对应设备驱动的结构体platform_driver,然后在调用platform_driver中的探测函数函数。