本节知识点:
基础知识:
1.把最近学的东西串串线,首先学的是kobject,这个东西是在sysfs文件系统中,创建一个目录的基类,在这点上linux有着面向对象的编程思想,也就是什么kset,总线,platform都是继承了kobject的特性,在sys目录中创建目录。
2.学习kobject和kset是为了学习总线设备驱动模型的,因为创建总线,设备,驱动实际就是在/sys/bus目录中创建kobject,其实质也是kobject和kset完成的。
3.platform平台总线驱动模型,其实就是linux内核把,上节那个总线设备驱动模型进行了封装。把本应该自己创建的一条总线,变成了linux替你创建好的一条platform总线而已。
4.这里有一个很迷茫的一点就是,这个platform平台总线驱动模型到底有什么用??我现在的理解是这样的,希望在读了宋宝华的linux设备驱动之后还有体会。
第一:platform将设备本身的资源注册进入内核,由内核统一管理,在驱动程序使用这些资源的时候使用统一的接口,提高驱动的可移植性。
第二:这是一个很常用的驱动模型,也叫框架吧,linux设备驱动 叫他是工程中的驱动。
第三:这模型仅仅是将驱动和设备分开,然后当有新设备或者新驱动的时候,去匹配,匹配成功再调用driver模块中的probe函数,完成具体的驱动程序。也就是说platform仅仅是一个框架,功能驱动在probe函数里面,是字符驱动,还是块驱动啊 都是在probe函数里面完成。
驱动结构及重要函数:
在platform_device里面:
1.在struct platform_device结构体中 填写设备名称,id,设备资源结构,或者通过struct platform_device *platform_device_alloc(const char *name,int id)函数来定义platform_device
2.platform_device_register(&led_dev)注册平台设备进入内核
在platform_driver里面:
1.在struct platform_driver led_drv={
.probe=led_drv_probe,
.remove=led_drv_remove,
.driver={
.owner=THIS_MODULE,
.name="plat_led", //platform总线 里面驱动的名字 这个名字要和设备的名字一样
}
};里面定义 驱动名字 ,probe函数等
.probe=led_drv_probe,
.remove=led_drv_remove,
.driver={
.owner=THIS_MODULE,
.name="plat_led", //platform总线 里面驱动的名字 这个名字要和设备的名字一样
}
};里面定义 驱动名字 ,probe函数等
2.利用platform_driver_register(&led_drv) 注册驱动进入内核
其实国嵌在这里的时候看了内核代码的,有几个结论如下:
1.platform总线,就是内核定义的一条总线,并且将他的设备和驱动进行了封装
2.找到了bus_for_each_dev, 这个函数是总线在不断的轮询总线中的dev设备,然后通过match函数,判断设备和驱动是否匹配
3.platform的match就是比较platform_device.name和platform_driver.driver.name
本节代码:
plat-dev.c:
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> #include <linux/init.h> #include <linux/platform_device.h> MODULE_AUTHOR("Hao"); MODULE_LICENSE("Dual BSD/GPL"); struct platform_device led_dev={ .name="plat_led", //platform总线 里面设备的名字 这个名字要和驱动的名字一样 .id=-1, }; static int __init platform_led_dev_init(void) { int ret=0; ret=platform_device_register(&led_dev); if(ret) { printk("platform_device_register failed!!\n"); } return ret; } static void __exit platform_led_dev_exit(void) { platform_device_unregister(&led_dev); } module_init(platform_led_dev_init); module_exit(platform_led_dev_exit);
plat-drv.c:
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> #include <linux/init.h> #include <linux/platform_device.h> MODULE_AUTHOR("Hao"); MODULE_LICENSE("Dual BSD/GPL"); static int led_drv_probe(struct platform_device *dev) //这里面写功能驱动 { printk("Driver found device which my driver can handle!\n"); return 0; } static int led_drv_remove(struct platform_device *dev) { printk("Driver found device unpluged!\n"); return 0; } struct platform_driver led_drv={ .probe=led_drv_probe, .remove=led_drv_remove, .driver={ .owner=THIS_MODULE, .name="plat_led", //platform总线 里面驱动的名字 这个名字要和设备的名字一样 } }; static int __init platform_led_drv_int(void) { return platform_driver_register(&led_drv); } static void __exit platform_led_drv_exit(void) { platform_driver_unregister(&led_drv); } module_init(platform_led_drv_int); module_exit(platform_led_drv_exit);