标签:name driver bus 模型 总线 init device 驱动 my
1、引言
待补充,总线是linux设备驱动的一种软件架构思想。
2、总线概述
总线设备驱动一共分为3步,第一是学习总线,第二是学习设备,第三步是学习驱动。
这张图不全,不管是总线还是设备还是驱动,都分为结构描述、注册、注销这三部分。
2.1第一步:总线创建-结构体-注册-注销
如何创建一条总线?
bus.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> MODULE_LICENSE("GPL"); int my_match(struct device *dev, struct device_driver *drv) { //两个结构体,一个代表设备,一个代表驱动 return 0; } struct bus_type my_bus_type={ .name = "my_bus", .match = my_match, }; EXPORT_SYMBOL(my_bus_type); int my_bus_init(void) { int ret=0; ret = bus_register(&my_bus_type); } void my_bus_exit(void) { bus_unregister(&my_bus_type); } module_init(my_bus_init); module_exit(my_bus_exit);
:加载之后,会在sys/bus总线目录下多出来我们定义的总线
2.2 如何创建驱动?并且挂载在上面的总线上
driver.c
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> MODULE_LICENSE("GPL"); extern struct bus_type my_bus_type; int my_probe(struct device *dev)//谁来触发probe函数呢??? { printk("driver found the device it can handler\n"); return 0; } struct device_driver my_driver = { .name = "my_dev", .bus = &my_bus_type,//这里引用了上面创建的总线结构体 .probe = my_probe, }; int my_driver_init(void) { int ret; ret = driver_register(&my_driver); } void my_driver_exit(void) { driver_unregister(&my_driver); } module_init(my_driver_init); module_exit(my_driver_exit); Makefile obj-m := bus.o driver.o KDIR := /home/aston/040-linux-tq2440/linux-tq2440 all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order
2.3 第三步:如何创建并且在总线上挂载一个设备??
前面两步我们已经加载好了总线和驱动
device.c #include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> MODULE_LICENSE("GPL"); extern struct bus_type my_bus_type; struct device my_device={ .init_name = "my_device", .bus = &my_bus_type, }; int my_device_init(void) { int ret; ret = device_register(&my_device); } void my_device_exit(void) { device_unregister(&my_device); } module_init(my_device_init); module_exit(my_device_exit);
问题1、设备上线后,谁来触发driver的probe函数??谁来粗发bus的match函数??
这个应该在内核里面有答案,match匹配到之后,才会调用到对应的驱动。也就说上层有地方会持续的扫描调用match函数,或者由中断触发。当发现有device上线后,match会拿着device的name去逐一和当前的driver的name进行匹配。找到之后就会调用probe函数。这也是到现在为止,把这几个ko加载后没反应的原因。
需要修改bus.c bus.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> MODULE_LICENSE("GPL"); int my_match(struct device *dev, struct device_driver *drv) { //两个结构体,一个代表设备,一个代表驱动 //return !strncmp(dev->init_name,drv->name,strlen(drv->name)); //上电后发现init_name是空指针,导致出现堆栈回溯异常 return !strncmp(dev->kobj.name, drv->name, strlen(drv->name)); } /*在添加设备时 int device_add(struct device *dev) 问题:这个函数在什么时候被调用呢???? { if (dev->init_name) { dev_set_name(dev, "%s", dev->init_name); dev->init_name = NULL;所以我们需要比较的是dev->kobj.name } } */ struct bus_type my_bus_type={ .name = "my_bus", .match = my_match; }; EXPORT_SYMBOL(my_bus_type); int my_bus_init() { int ret=0; ret = bus_register(&my_bus_type); } void my_bus_exit() { bus_unregister(&my_bus_type); } module_init(my_bus_init); module_init(my_bus_exit); Makefile obj-m := bus.o driver.o device.o KDIR := /home/aston/040-linux-tq2440/linux-tq2440 all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order
问题1:device_add函数由谁来调用??
标签:name,driver,bus,模型,总线,init,device,驱动,my 来源: https://www.cnblogs.com/luckdog0623/p/16365656.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。