木其工作室(专业程序代写服务)[原]ok6410学习笔记(13.总线设备驱动)
2013-06-27 11:19
429 查看
优质代写程序 代写Assignment程序 定制软件 设计程序 专业代写IT 大学生程序代写
1.总线结构:
name是总线的名称,即总线在bus目录下面 文件夹的名称
bus_attribute device_attribute driver_attribute分别是总线 设备 驱动三者的属性文件的描述 如图
他们分别是通过三个宏完成赋值的 下面详细说明
2.设备结构:
kobject kobj是device自身的文件夹名字 来源init_name的赋值
3.驱动结构:
name驱动名称 在my_bus中drives里面的文件夹名
probe当bus模块调用match匹配成功的时候 调用probe函数
4.三个重要的宏:
BUS_ATTR 在linux内核中源码为
DRIVER_ATTR 在linux内核中源码为
DEVICE_ATTR 在linux内核中源码为
他们都是在给自己的attribute结构赋值 这个结构是用来创建属性文件的 name是属性文件的名字 /sys/bus目录中my_bus(自己给bus_type.name赋的值) 下面的属性文件
mode为文件读写属性 show为读该文件时调用的函数 store为写该文件时调用的函数
这里还创建出了bus_attr_##_name结构体 是在bus_create_file创建属性文件函数参数中使用的 注意连接符## 所有一定要匹配好
创建的my_bus总线里面有:
其中devices是用来存放设备的 drives是用来存放驱动的 mybus就是刚刚说的属性文件 是通过宏创建的
创建的driver模块里面有:
这个路径是 /sys/bus/my_bus/drivers/my_dev里面的内容 目录本身的my_dev是在driver结构体中给name赋值得到的 mydriver是 在创建属性文件的宏中的_name得到的
创建的device模块里面有:
这个my_dev是在device结构中给 init_name 赋值得到的目录 跟在bus中match比较函数中的kobject的值是一个 他本身是一个连接 连接到/sys/devices/my_bus_dev/my_dev目录中
/sys/devices/my_bus_dev/my_dev目录:
这个连接到的目录中的mydevice就是 利用宏创建的属性文件 名字跟宏中的_name是一个值
5.对于安装driver模块和device模块的顺序问题:先安装那个都可以 都是在有新设备或者新驱动的时候 总线中的match函数进行匹配(这里我觉得是利用了热插拔性质) 然后匹配成功调用driver里面的probe函数
6.注意:bus模块 device模块 driver模块是三个内核模块 而不是简单的三个文件之间的函数调用那么简单,所有在device模块 和 driver模块 中想利用bus模块中的my_bus_dev和my_bus_type的时候,应该使用EXPORT_SYMBOL(my_bus_dev); EXPORT_SYMBOL(my_bus_type);
7.这里面有一个不懂的地方,在调用match的时候dev->init_name这个值总是NULL 不是很理解 我觉得应该是device模块中我赋的值啊~~~~~
8.bus模块和device模块中的release函数就算是空函数,也必须要有,因为在卸载两个设备的的时候要调用的 貌似driver模块中的remove函数可以没有的
2.bus_unregister(&my_bus_type) 注销总线
3.bus_create_file(&my_bus_type, &bus_attr_mybus) 创建总线设备文件
4.bus_remove_file(&my_bus_type, &bus_attr_mybus) 删除总线设备文件
5.int my_match (struct device *dev, struct device_driver *driver) 匹配指定的驱动程序能否处理指定的设备
6.device_register(&my_dev) 注册设备
7.device_unregister(&my_dev) 删除设备
8.device_create_file(&my_dev, &dev_attr_mydevice) 给device模块创建设备文件
9.device_remove_file(&my_dev, &dev_attr_mydevice) 给device模块删除设备文件
10.driver_register(&my_driver) 注册驱动
11.driver_unregister(&my_driver) 删除驱动
12.driver_create_file(&my_driver, &driver_attr_mydriver) 创建驱动属性文件
13.driver_remove_file(&my_driver, &driver_attr_mydriver) 删除驱动属性文件
1.先在bus模块中 填写 struct bus_type my_bus_type和struct device my_bus_dev
确定总线的名字 即总线目录的名字 即match函数的名字
2.bus_register(&my_bus_type) 注册总线设备 my_match (struct device *dev, struct device_driver *driver)写match函数 注意判断匹配成功的条件 一旦成功在driver模块中则调用probe函数
3.利用宏BUS_ATTR(mybus, S_IRUGO, show_bus_mybus, NULL) 和 bus_create_file(&my_bus_type, &bus_attr_mybus)创建总线属性文件 mybus为属性文件的名字
4.总线也是一个设备,所有要创建总线设备device_register(&my_bus_dev) 设备中的内容来自第一步中struct device my_bus_dev结构
其实这个结构中总线设备的名字.name = "my_bus" 我觉得没什么用
device模块:
5.填写struct device_driver my_driver 设备结构 包括.init_name = "my_dev"即设备目录的名字 ,.bus = &my_bus_type所属总线,.parent = &my_bus_dev所属父对象,.release = my_dev_release 卸载函数
6.device_register(&my_dev)创建设备
7.DEVICE_ATTR(mydevice, S_IRUGO, mydev_show, NULL)和device_create_file(&my_dev, &dev_attr_mydevice)创建属性文件 文件名叫mydevice
driver模块:
8.填写struct device_driver my_driver 驱动结构 包括.name = "my_dev"驱动目录的名字 一般用来 和device设备名字一起用作bus模块中match函数 ,.bus = &my_bus_type所属总线 .probe = my_probe probe函数
9.driver_register(&my_driver) 注册一个驱动
10.DRIVER_ATTR(mydriver, S_IRUGO, mydriver_show, NULL)和driver_create_file(&my_driver, &driver_attr_mydriver)创建一个驱动的属性文件 文件名为mydriver
device.c:
driver.c:
Makefile:
作者:qq418674358 发表于2013-6-27 11:19:29 原文链接
阅读:58 评论:0 查看评论
1.总线结构:
name是总线的名称,即总线在bus目录下面 文件夹的名称
bus_attribute device_attribute driver_attribute分别是总线 设备 驱动三者的属性文件的描述 如图
他们分别是通过三个宏完成赋值的 下面详细说明
2.设备结构:
kobject kobj是device自身的文件夹名字 来源init_name的赋值
3.驱动结构:
name驱动名称 在my_bus中drives里面的文件夹名
probe当bus模块调用match匹配成功的时候 调用probe函数
4.三个重要的宏:
BUS_ATTR 在linux内核中源码为
#define BUS_ATTR(_name, _mode, _show, _store) \ struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
DRIVER_ATTR 在linux内核中源码为
#define DRIVER_ATTR(_name, _mode, _show, _store) \ struct driver_attribute driver_attr_##_name = \ __ATTR(_name, _mode, _show, _store)
DEVICE_ATTR 在linux内核中源码为
#define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
他们都是在给自己的attribute结构赋值 这个结构是用来创建属性文件的 name是属性文件的名字 /sys/bus目录中my_bus(自己给bus_type.name赋的值) 下面的属性文件
mode为文件读写属性 show为读该文件时调用的函数 store为写该文件时调用的函数
这里还创建出了bus_attr_##_name结构体 是在bus_create_file创建属性文件函数参数中使用的 注意连接符## 所有一定要匹配好
创建的my_bus总线里面有:
其中devices是用来存放设备的 drives是用来存放驱动的 mybus就是刚刚说的属性文件 是通过宏创建的
创建的driver模块里面有:
这个路径是 /sys/bus/my_bus/drivers/my_dev里面的内容 目录本身的my_dev是在driver结构体中给name赋值得到的 mydriver是 在创建属性文件的宏中的_name得到的
创建的device模块里面有:
这个my_dev是在device结构中给 init_name 赋值得到的目录 跟在bus中match比较函数中的kobject的值是一个 他本身是一个连接 连接到/sys/devices/my_bus_dev/my_dev目录中
/sys/devices/my_bus_dev/my_dev目录:
这个连接到的目录中的mydevice就是 利用宏创建的属性文件 名字跟宏中的_name是一个值
5.对于安装driver模块和device模块的顺序问题:先安装那个都可以 都是在有新设备或者新驱动的时候 总线中的match函数进行匹配(这里我觉得是利用了热插拔性质) 然后匹配成功调用driver里面的probe函数
6.注意:bus模块 device模块 driver模块是三个内核模块 而不是简单的三个文件之间的函数调用那么简单,所有在device模块 和 driver模块 中想利用bus模块中的my_bus_dev和my_bus_type的时候,应该使用EXPORT_SYMBOL(my_bus_dev); EXPORT_SYMBOL(my_bus_type);
7.这里面有一个不懂的地方,在调用match的时候dev->init_name这个值总是NULL 不是很理解 我觉得应该是device模块中我赋的值啊~~~~~
8.bus模块和device模块中的release函数就算是空函数,也必须要有,因为在卸载两个设备的的时候要调用的 貌似driver模块中的remove函数可以没有的
重点函数:
1. bus_register(&my_bus_type)注册总线进入系统2.bus_unregister(&my_bus_type) 注销总线
3.bus_create_file(&my_bus_type, &bus_attr_mybus) 创建总线设备文件
4.bus_remove_file(&my_bus_type, &bus_attr_mybus) 删除总线设备文件
5.int my_match (struct device *dev, struct device_driver *driver) 匹配指定的驱动程序能否处理指定的设备
6.device_register(&my_dev) 注册设备
7.device_unregister(&my_dev) 删除设备
8.device_create_file(&my_dev, &dev_attr_mydevice) 给device模块创建设备文件
9.device_remove_file(&my_dev, &dev_attr_mydevice) 给device模块删除设备文件
10.driver_register(&my_driver) 注册驱动
11.driver_unregister(&my_driver) 删除驱动
12.driver_create_file(&my_driver, &driver_attr_mydriver) 创建驱动属性文件
13.driver_remove_file(&my_driver, &driver_attr_mydriver) 删除驱动属性文件
驱动结构:
bus模块:1.先在bus模块中 填写 struct bus_type my_bus_type和struct device my_bus_dev
确定总线的名字 即总线目录的名字 即match函数的名字
2.bus_register(&my_bus_type) 注册总线设备 my_match (struct device *dev, struct device_driver *driver)写match函数 注意判断匹配成功的条件 一旦成功在driver模块中则调用probe函数
3.利用宏BUS_ATTR(mybus, S_IRUGO, show_bus_mybus, NULL) 和 bus_create_file(&my_bus_type, &bus_attr_mybus)创建总线属性文件 mybus为属性文件的名字
4.总线也是一个设备,所有要创建总线设备device_register(&my_bus_dev) 设备中的内容来自第一步中struct device my_bus_dev结构
其实这个结构中总线设备的名字.name = "my_bus" 我觉得没什么用
device模块:
5.填写struct device_driver my_driver 设备结构 包括.init_name = "my_dev"即设备目录的名字 ,.bus = &my_bus_type所属总线,.parent = &my_bus_dev所属父对象,.release = my_dev_release 卸载函数
6.device_register(&my_dev)创建设备
7.DEVICE_ATTR(mydevice, S_IRUGO, mydev_show, NULL)和device_create_file(&my_dev, &dev_attr_mydevice)创建属性文件 文件名叫mydevice
driver模块:
8.填写struct device_driver my_driver 驱动结构 包括.name = "my_dev"驱动目录的名字 一般用来 和device设备名字一起用作bus模块中match函数 ,.bus = &my_bus_type所属总线 .probe = my_probe probe函数
9.driver_register(&my_driver) 注册一个驱动
10.DRIVER_ATTR(mydriver, S_IRUGO, mydriver_show, NULL)和driver_create_file(&my_driver, &driver_attr_mydriver)创建一个驱动的属性文件 文件名为mydriver
本节代码:
bus.c:#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_AUTHOR("Hao"); MODULE_LICENSE("Dual BSD/GPL"); static void my_bus_release(struct device *dev) { printk("call my_bus_release\n"); } static int my_match (struct device *dev, struct device_driver *driver) //处理Device和driver两个结构 { printk("call my_match\n"); printk("dev->init_name = %s\n", dev->init_name); printk("dev->kobj.name = %s\n", dev->kobj.name); //很好奇想看看这个值是什么 这里面的文件即目录直接的关系弄的很乱 printk("driver->name = %s\n", driver->name); if(strcmp(dev->kobj.name, driver->name)) return 0; else return 1; } struct bus_type my_bus_type = { //总线的结构体 .name = "my_bus", //总线的名字 sys下面bus中的总线名字 .match = my_match, //用来比较设备和驱动的对应关系的 }; struct device my_bus_dev = { //总线设备的结构体 .init_name = "my_bus_dev", //这个是 设备的名字 .release = my_bus_release //这个应该是移除设备的时候调用的函数 就算是空函数也一定要有的 }; EXPORT_SYMBOL(my_bus_dev);//这两个是 内核模块之间传递的参数 这个传递给device模块的 赋值给parent父设备的 EXPORT_SYMBOL(my_bus_type); //这个是传递给driver和device两个模块的 让他们知道所属的总线 static ssize_t show_bus_mybus(struct bus_type *bus, char *buf) { strcpy(buf,"catting the my_bus\n"); //这个应该是在读取my_bus下面属性文件的时候 传递给用户空间的 return strlen(buf); //这里应该返回buf的大小 愿意跟kobject那里说的一样 } static BUS_ATTR(mybus, S_IRUGO, show_bus_mybus, NULL);//这个宏的第一个参数是名字是bus_attr_mybus结构体的名字 第二个参数是文件属性 第三个show函数 第四个store函数 static int __init my_bus_init(void) { int ret; printk("call my_bus_init!!!\n"); ret = bus_register(&my_bus_type); //注册总线进入系统 if (ret) return ret; if (bus_create_file(&my_bus_type, &bus_attr_mybus)) //创建属性文件 在my_bus_type这个总线上面创建属性文件 属性文件取决于bus_attr_mybus这个结构体 这个结构体应该看这个BUS_ATTR宏 printk("Fail to create version attribute!\n"); ret = device_register(&my_bus_dev); //总线也是一个设备 所以应该注册总线设备 if (ret) printk("Fail to register device : my_bus!\n"); return ret; } static void __exit my_bus_exit(void) { printk("call my_bus_exit\n"); device_unregister(&my_bus_dev); bus_unregister(&my_bus_type); } module_init(my_bus_init); module_exit(my_bus_exit);
device.c:
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_AUTHOR("Hao"); MODULE_LICENSE("Dual BSD/GPL"); extern struct device my_bus_dev; extern struct bus_type my_bus_type; static void my_dev_release(struct device *dev) { printk("call my_bus_release\n"); } struct device my_dev = { .init_name = "my_dev", //my_bus中设备的名字 是个连接 连接到sys/device目录下 .bus = &my_bus_type, //所属总线 .parent = &my_bus_dev, //总线自身就是设备 即父设备 .release = my_dev_release, }; static ssize_t mydev_show(struct device *dev, struct device_attribute *attr, char *buf) //这里的struct device_attribute *attr 应该是来自 DEVICE_ATTR这个宏传递给内核的 { strcpy(buf,"catting the my_dev\n"); //这个应该是在读取my_bus下面属性文件的时候 传递给用户空间的 return strlen(buf); //这里应该返回buf的大小 愿意跟kobject那里说的一样 } static DEVICE_ATTR(mydevice, S_IRUGO, mydev_show, NULL); //mydevice貌似是文件名 static int __init my_device_init(void) { int ret = 0; ret = device_register(&my_dev); //注册设备 if (ret) return ret; ret =device_create_file(&my_dev, &dev_attr_mydevice); //创建device的设备文件 方式跟bus的一样 也是通过一个宏 return ret; } static void my_device_exit(void) { device_unregister(&my_dev); } module_init(my_device_init); module_exit(my_device_exit);
driver.c:
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_AUTHOR("Hao"); MODULE_LICENSE("Dual BSD/GPL"); extern struct bus_type my_bus_type; static int my_probe(struct device *dev) { printk("Driver found device which my driver can handle!\n"); return 0; } static int my_remove(struct device *dev) { printk("Driver found device unpluged!\n"); return 0; } struct device_driver my_driver = { .name = "my_dev", //驱动的名字 这个要跟设备的名字一样 不然不匹配probe不能触发的 .bus = &my_bus_type, //所属的总线 .probe = my_probe, //如果匹配到设备 匹配的是通过总线中match函数进行的 则触发这个函数 .remove = my_remove, //如果移除这个驱动则调用这个函数 }; static ssize_t mydriver_show(struct device_driver *driver, char *buf) { strcpy(buf,"catting the my_driver\n"); //这个应该是在读取my_bus下面属性文件的时候 传递给用户空间的 return strlen(buf); //这里应该返回buf的大小 愿意跟kobject那里说的一样 } static DRIVER_ATTR(mydriver, S_IRUGO, mydriver_show, NULL); static int __init my_driver_init(void) { int ret = 0; ret = driver_register(&my_driver); //注册驱动 if (ret) return ret; ret = driver_create_file(&my_driver, &driver_attr_mydriver); //创建驱动属性文件 return ret; } static void my_driver_exit(void) { driver_unregister(&my_driver); } module_init(my_driver_init); module_exit(my_driver_exit);
Makefile:
ifneq ($(KERNELRELEASE),) obj-m := bus.o devices.o driver.o else KDIR := /guoqian/linux/linux-2.6.36 all: make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux- clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul* endif
作者:qq418674358 发表于2013-6-27 11:19:29 原文链接
阅读:58 评论:0 查看评论
相关文章推荐
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(15.platform平台总线驱动模型之混杂设备驱动led)
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(14.platform平台总线驱动模型)
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(19.块设备驱动程序设计)
- 木其工作室(专业程序代写服务)[转]学写块设备驱动(一)----了解gendisk及request处理函数
- 木其工作室(专业程序代写服务)[转]学写块设备驱动(二)----更换IO调度器
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(16.按键中断控制led驱动)
- 木其工作室(专业程序代写服务)[转]学写块设备驱动(三)----踢开IO调度器,自己处理bio(上)
- 木其工作室(专业程序代写服务)[转]学写块设备驱动(三)----踢开IO调度器,自己处理bio(下)
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(12.kset学习记录)
- 木其工作室(专业程序代写服务)[转]linux块设备读写流程(一篇很难的块设备文件 没怎么看懂)
- 木其工作室(专业程序代写服务)[转]Linux设备驱动程序学习-中断处理
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(17.中断下部分之工作队列)
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(11.kobject学习记录)
- 木其工作室(专业程序代写服务)[转]每个程序员都应该学习使用Python或Ruby
- 木其工作室(专业程序代写服务)[原]数据结构学习笔记(1.大O表示法和顺序表)
- 木其工作室(专业程序代写服务)[原]c语言复习课程1(唐老师答疑课)
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(18.linux串口驱动程序设计)
- 木其工作室(专业程序代写服务)
- 木其工作室(专业程序代写服务)[转]linux中断处理体系结构
- 总线设备驱动框架程序 及 struct device中消失的bus_id的取代方法