前⾔: 对于linux platform device 和driver,⼀个driver可对应多个device,通过名字进⾏匹配,调⽤驱动⾥边实现的probe函数,本⽂以⼀个i2c设备为例,从驱动的i2c_add_driver()开始看源码以及⽤⽐较笨的打log的⽅式分析如何⼀步⼀步调⽤的probe()函数。 分析的代码基于linux kernel msm-4.9。
/****************************************/
从module_init()开始看,
定义位置:////
源码⾥对该函数的说明:
/**
* module_init() - driver initialization entry point金折网
* @x: function to be run at kernel boot time or module insertion
*
* module_init() will either be called during do_initcalls() (if
* builtin) or at module insertion time (if a module). There can only
* be one per module.
*/
作为每个驱动的⼊⼝函数,若代码有编译进kernel的话在开机kernel 启动(或模块被动态加载的时候)的时候被do_initcalls()调⽤, 从kernel如何⼀步⼀步⾛到do_initcalls()进⽽调⽤module_init(),调⽤链如下:
start_kernel();//kernel的第⼀个函数
();
();
();
();
();//
();
//......
module_init();
/*************************************/
接着通过module_init()调⽤你在驱动⾥边实现的init函数:
对于⼀个i2c设备来说,做法如下,
static struct i2c_driver your_driver = {
.driver = {
.owner = THIS_MODULE,
.
name = YOUR_DRIVER_NAME_UP,
.of_match_table = your_driver_of_match,
},
.probe = your_probe_func,
.remove = your_i2c_drv_remove,
.id_table = your_i2c_drv_id_table,
//.suspend = your_i2c_drv_suspend,
//.resume = your_i2c_drv_resume,
};
static int __int your_init_func(void)
{
/
/…
i2c_add_driver(&your_i2c_driver);
//…
}
modul_init(your_init_func);
将 your_probe_func()地址装进你实现的struct i2c_driver的.probe 成员,接下来,从i2c_add_driver()如何调⽤到你的probe函数,调⽤链如下:
i2c_register_driver();
driver_register();
bus_add_driver();
driver_attach();
__driver_attach (for your device);
driver_probe_device();
really_probe();
i2c_device_probe (this is what dev->bus->probe is for an i2c driver);
your_probe_func();
接下来⼀个⼀个函数分析他们到底⼲了什么:
先看i2c_register_driver(),
定义位置:kernel/msm-4.9/drivers/i2c/i2c-core.c
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
/* Can't register until after driver model init */
if (WARN_ON(!is_registered)) {
printk("unlikely(WARN_ON(!i2c_bus_type.p and return -EAGAIN.\n");
安全刀具return -EAGAIN;氢气炉
}
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;//这边添加了bus type
INIT_LIST_HEAD(&driver->clients);
/* When registration returns, the driver core
* will have called probe() for all matching-but-unbound devices.
*/
res = driver_register(&driver->driver); //这边⾛进去
if (res){
printk("driver_register return res : %d\n", res);
return res;
}
pr_debug("driver [%s] registered\n", driver->driver.name);
无人机测量
printk(KERN_INFO "======>lkhlog %s\n",driver->driver.name);
/* iWalk the adapters that are already present */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
type定义如下:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,//后⾯会回调这个函数,在上⾯的调⽤链⾥有提到 .remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
};
合规管理系统添加了bus_type,然后调⽤driver_register(),
接着看driver_register(),
定义位置:kernel/msm-4.9/drivers/base/driver.c
* driver_register - register driver with bus 注册总线驱动,和总线类型联系起来 * @drv: driver to register *
胎压监测装置* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
//……
other = driver_find(drv->name, drv->bus);//确认该驱动是否已经注册过
printk(KERN_WARNING "======>lkh driver_find, other : %d", other);
//……
ret = bus_add_driver(drv);//主要从这⼉⾛进去
printk(KERN_WARNING "======>lkh bus_add_driver, ret : %d", ret);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret) {
printk(KERN_WARNING "======>lkh bus_remove_driver");
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
return ret;
}
接着看 bus_add_driver(),
定义位置:kernel/msm-4.9/drivers/base/bus.c
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/
int bus_add_driver(struct device_driver *drv)
{
bus = bus_get(drv->bus);//重新获取到前边装进去的bus
if (!bus) {
printk(KERN_ERR "======>lkh return -EINVAL\n");
return -EINVAL;
}
printk(KERN_ERR "======>lkh bus_add_driver\n");
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;//driver_private ⾥边指针指向device_driver
drv->p = priv;
//device_driver也有指针指向driver_private,这样就可通过其中⼀个获取到另外⼀个
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
if (drv->bus->p->drivers_autoprobe) {
printk(KERN_ERR "======>lkh drv->bus->p->drivers_autoprobe == true, name : %s\n", drv->name); if (driver_allows_async_probing(drv)) {
pr_debug("bus: '%s': probing driver %s asynchronously\n",
drv->bus->name, drv->name);
printk(KERN_ERR "======>lkh bus: '%s': probing driver %s asynchronously\n",
drv->bus->name, drv->name);
async_schedule(driver_attach_async, drv);
} else {
printk(KERN_ERR "======>lkh enter driver_attach, name : %s\n", drv->name);
error = driver_attach(drv);//这边⾛进去
printk(KERN_ERR "======>lkh driver_attach, error : %d\n", error);
if (error)
goto out_unregister;
}
}
printk(KERN_ERR "======>lkh bus_add_driver 2, name : %s \n", drv->name);
//若前边driver_attach()返回没有错误的话,
//这边会进去创建相关节点,链接
module_add_driver(drv->owner, drv);
//……
}
接着看driver_attach(),直接看函数说明就能明⽩了,
定义位置:kernel/msm-4.9/drivers/base/dd.c