用一个.c文件来理解bus,driver,device,sysfs的关系和driver&device的bind过程
忙了一个下午,调成功了一个module.写出来可能对驱动新手有一定帮助。我本人就是新手,所以从源码中理解这些概念花了一定的功夫。
以下module可以验证device,driver,bus的关系及在sysfs的体系,及bus先match,driver再probe的过程。
同时追求代码最小化,可见bus,device,driver等对象在注册时哪些信息是必须的。
- #include <linux/module.h>
- #include <linux/kobject.h>
- #include <linux/device.h>
- /*未实现设备文件创建和文件系统驱动*/
- static int my_bus_match(struct device* device, struct device_driver* driver);
- static int my_driver_probe(struct device* dev);
- static void unregister_all(void);
- static int register_all(void);
- MODULE_LICENSE("GPL");
- struct bus_type my_bus_type =
- {
- .name = "my_bus_type",
- .match= my_bus_match
- };
- struct my_device
- {
- int id;
- struct device dev;
- int drv_id;
- };
- struct my_device_driver
- {
- int id;
- struct device_driver drv;
- };
- struct my_device_driver my_driver_1 =
- {
- .drv =
- {
- .name = "my_bus_driver_1",
- .probe = my_driver_probe,
- .bus = &my_bus_type,
- },
- .id = 1,
- };
- struct my_device_driver my_driver_2 =
- {
- .drv =
- {
- .name = "my_bus_driver_2",
- .probe = my_driver_probe,
- .bus = &my_bus_type
- },
- .id = 2
- };
- struct my_device my_device_1 =
- {
- .id=001,
- .drv_id = 1,
- .dev =
- {
- .bus = &my_bus_type,
- .bus_id = "my_bus_id_1"
- }
- };
- struct my_device my_device_2 =
- {
- .id=002,
- .drv_id = 2,
- .dev =
- {
- .bus = &my_bus_type,
- .bus_id = "my_bus_id_2"
- }
- };
- static int device_match_driver(struct my_device* mydev, struct my_device_driver* mydrv)
- {
- printk("one match tested: dev_id=%d, dev.drv_id=%d, drv_id=%d, drv_name=%s\n", mydev->id,
- mydev->drv_id, mydrv->id, mydrv->drv.name );
- if(mydev->drv_id != mydrv->id)
- return 0;
- return 1;
- }
- static int my_bus_match(struct device* device, struct device_driver* driver)
- {
- struct my_device* mydev = container_of(device, struct my_device, dev);
- struct my_device_driver* mydrv = container_of(driver, struct my_device_driver, drv);
- printk("my_bus_match called\n");
- if(device_match_driver(mydev, mydrv))
- {
- printk("one matched group:dev_id=%d drv_id=%d\n", mydev->id, mydrv->id);
- return 1;
- }
- printk("device %d and driver %d not match\n", mydev->id, mydrv->id);
- return 0;
- }
- static int my_driver_probe(struct device* dev)
- {
- struct my_device_driver* mydrv = container_of(dev->driver, struct my_device_driver, drv);
- struct my_device* mydev = container_of(dev, struct my_device, dev);
- printk("my_driver %s drive probe called\n", mydrv->drv.name);
- if(device_match_driver(mydev, mydrv))
- return 0;
- return 1;
- }
- const int errExist = -17;
- int bus_is_registered = 0;
- static int register_all()
- {
- int res;
- res = bus_register(&my_bus_type);
- if(res)
- {
- printk("register my_bus_type failed\n");
- return res;
- }
- bus_is_registered = 1;
- /*register driver 1*/
- res = driver_register(&my_driver_1.drv);
- if(res)
- {
- printk("register my_driver_1 failed\n");
- return res;
- }
- /*register driver 2*/
- res = driver_register(&my_driver_2.drv);
- if(res)
- {
- printk("register my_driver_2 failed\n");
- return res;
- }
- /*add device 1*/
- res = device_register(&my_device_1.dev);
- if(res)
- {
- printk("register my_device_1 failed\n");
- return res;
- }
- res = device_register(&my_device_2.dev);
- if(res)
- {
- printk("register my_device_2 failed\n");
- return res;
- }
- return 0;
- }
- static int my_init(void)
- {
- int res;
- printk("my_init called\n");
- if((res = register_all()))
- {
- if(res != errExist && bus_is_registered)
- bus_unregister(&my_bus_type);
- /* dangerous if call unregister_all();*/
- printk("res=%d\n",res);
- return res;
- }
- return 0;
- }
- static void unregister_all()
- {
- device_unregister(&my_device_1.dev);
- device_unregister(&my_device_2.dev);
- driver_unregister(&my_driver_1.drv);
- driver_unregister(&my_driver_2.drv);
- bus_unregister(&my_bus_type);
- }
- static void my_exit(void)
- {
- unregister_all();
- }
- module_init(my_init);
- module_exit(my_exit);
复制代码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
:wink:
LDD 里面讲得也不错~