2.the linux device model--bus device driver
来源:互联网 发布:皮卡刻字机端口设置 编辑:程序博客网 时间:2024/05/22 12:07
Linux中,分别使用bus_type,device_driver,device来描述总线,驱动和设备,在设备模型中,所有的设备都通过总线来连接。即使有些设备没有连接到一根物理总线上,Linux为其设置了一个内部的、虚拟的platform总线,来维持总线、驱动、设备的关系。
<device.h>
总线:
点击(此处)折叠或打开
- struct bus_type {
- const char * name;//总线名字
- struct module * owner;
- struct kset subsys;//子系统,连接到一个全局变量kset bus_subsys。这样每一根总线系统都会通过bus_subsys结构连接起来。
- struct kset drivers;//总线驱动
- struct kset devices;//插入总线的所有设备
- struct bus_attribute * bus_attrs;
- struct device_attribute * dev_attrs;
- struct driver_attribute * drv_attrs;
- int (*match)(struct device * dev, struct device_driver * drv);
- int (*uevent)(struct device *dev, char **envp,int num_envp, char *buffer, int buffer_size);//参数与kset里的uevent相同。
- int (*probe)(struct device * dev);
- int (*remove)(struct device * dev);
- void (*shutdown)(struct device * dev);
- ....
- }
总线注册:bus_register(struct bus_type *bus);
总线删除:bus_unregister(struct bus_type *bus);
总线属性:
点击(此处)折叠或打开
- struct bus_attribute {
- struct attribute attr;
- ssize_t (*show)(struct bus_type *, char * buf);
- ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
- }
创建和初始化bus_attribute结构:
#define BUS_ATTR(_name,_mode,_show,_store)
创建总线属性:
int bus_create_file(struct bus_type *,struct bus_attribute *);
删除属性:
void bus_remove_file(struct bus_type *, struct bus_attribute *);
点击(此处)折叠或打开
- Bus.c
- #include <linux/device.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/string.h>
- #include <linux/sysfs.h>
- #include <linux/stat.h>
- #include <linux/mm.h>
- static ssize_t show_bus_author(struct bus_type *bus,char *buf) {
- return snprintf(buf,PAGE_SIZE,"%s\n","show_bus_author");
- }
- static int virtual_bus_match(struct device *dev,struct device_driver *drv) {
- Printk(KERN_DEBUG”\n!!!!!!match!!!!!!\n”);
- return !strcmp(dev_name(dev),drv->name);
- }
- void my_bus_release(struct device *dev) {
- printk(KERN_DEBUG"my bus release\n");
- }
- struct bus_type virtual_bus={
- .name = "virtual_bus",
- .match = virtual_bus_match,
- };
- struct device my_busdev={
- .init_name = "my_busdev",
- .release = my_bus_release,
- };
- EXPORT_SYMBOL(virtual_bus);
- EXPORT_SYMBOL(my_busdev);
- static BUS_ATTR(c,S_IRUGO,show_bus_author,NULL);
- static int __init bus_init(void) {
- int ret;
- ret=bus_register(&virtual_bus); //register virtual_bus
- if(ret){
- return ret;
- }
- if(bus_create_file(&virtual_bus,&bus_attr_c)) { //创建总线属性文件
- printk(KERN_NOTICE"unable to create bus attr\n");
- }
-
- ret = device_register(&my_busdev);
- if(ret) {
- printk(KERN_NOTICE"unable to register device\n");
- }
- printk("bus register success!\n");
- return 0;
- }
- static void __exit bus_exit(void) {
- bus_unregister(&virtual_bus);
- device_unregister(&my_busdev);
- }
- module_init(bus_init);
- module_exit(bus_exit);
- MODULE_AUTHOR("MANGO");
- MODULE_LICENSE("Dual BSD/GPL")
编译后,会在/sys/bus下建立virtual_bus文件夹。
执行cat c,得到如下输出:
设备驱动程序:
点击(此处)折叠或打开
- struct device_driver {
- const char * name;
- struct bus_type * bus;
- struct kobject kobj;
- struct klist klist_devices;
- struct klist_node knode_bus;
- struct module * owner;
- const char * mod_name; /* used for built-in modules */
- struct module_kobject * mkobj;
- int (*probe) (struct device * dev);
- int (*remove) (struct device * dev);
- void (*shutdown) (struct device * dev);
- int (*suspend) (struct device * dev, pm_message_t state);
- int (*resume) (struct device * dev);
- }
Driver.c
点击(此处)折叠或打开
- #include <linux/device.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/string.h>
- #include <linux/sysfs.h>
- #include <linux/stat.h>
- #include <linux/mm.h>
- extern struct device my_busdev;
- extern struct bus_type virtual_bus;
- extern struct device virtual_device;
- static ssize_t show_driver_author(struct device_driver *driver,char *buf) {
- return snprintf(buf,PAGE_SIZE,"%s\n","mango");
- }
- int my_driver_remove(struct device *dev) {
- printk("my_driver_remove\n");
- return 0;
- }
- int my_driver_probe(struct device *dev) {
- printk("my_driver_probe\n");
- return 0;
- }
- struct device_driver virtual_driver={
- .name = "mytest",
- .bus = &virtual_bus,
- .probe = my_driver_probe,
- .remove = my_driver_remove,
- };
- static DRIVER_ATTR(c,S_IRUGO,show_driver_author,NULL);
- static int __init my_driver_init(void) {
- int ret;
- ret = driver_register(&virtual_driver);
- if(ret)
- return ret;
- if(driver_create_file(&virtual_driver,&driver_attr_c))
- printk(KERN_NOTICE"unable to create author attr\n");
- printk("driver register success\n");
- return ret;
- }
- static void __exit my_driver_exit(void) {
- driver_unregister(&virtual_driver);
- printk("driver unregister success\n");
- }
- module_init(my_driver_init);
- module_exit(my_driver_exit);
- MODULE_AUTHOR("MANGO");
- MODULE_LICENSE("Dual BSD/GPL")
设备:
点击(此处)折叠或打开
- struct device {
- struct klist klist_children;
- struct klist_node knode_parent; /* node in sibling list */
- struct klist_node knode_driver;
- struct klist_node knode_bus;
- struct device *parent;//设备的父设备,大多数情况下,一个父设备是某种总线的宿主控制器。如果是NULL,则表示该设备是顶层设备。
- struct kobject kobj;//device->kobj->parent与&device->parent->kobj是相同的。
- char bus_id[BUS_ID_SIZE]; /* position on parent bus */
- struct device_type *type;
- ......
- struct bus_type * bus; /* type of bus device is on */
- struct device_driver *driver; /* which driver has allocated this
- device */
- void *driver_data; /* data private to the driver */
- ......
- void (*release)(struct device * dev);//当指向设备的最后一个引用被删除时,内核调用该方法。
- }
设备注册:int device_register(struct device *dev);
设备删除:int device_unregister(struct device *dev);
设备属性:
点击(此处)折叠或打开
- struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device *dev, struct device_attribute *attr,
- char *buf);
- ssize_t (*store)(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count);
- };
宏:#define DEVICE_ATTR(_name,_mode,_show,_store)
创建设备属性:
int device_create_file(struct device *device,struct device_attribute * entry);
删除设备属性:
void device_remove_file(struct device *dev,struct device_attribute *attr);
设置设备的名字:
dev_set_name(&dev, "name");
Device.c
点击(此处)折叠或打开- #include <linux/device.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/string.h>
- #include <linux/sysfs.h>
- #include <linux/stat.h>
- #include <linux/mm.h>
- extern struct device my_bus;
- extern struct bus_type virtual_bus;
- extern struct device virtual_device;
- static ssize_t show_driver_author(struct device_driver *driver,char *buf) {
- return snprintf(buf,PAGE_SIZE,"%s\n","mango");
- }
- int my_driver_remove(struct device *dev) {
- printk("my_driver_remove\n");
- return 0;
- }
- int my_driver_probe(struct device *dev) {
- printk("my_driver_probe\n");
- return 0;
- }
- struct device_driver virtual_driver={
- .name = "mytest",
- .bus = &virtual_bus,
- .probe = my_driver_probe,
- .remove = my_driver_remove,
- };
- static char *c="mango_attr";
- static DRIVER_ATTR(c,S_IRUGO,show_driver_author,NULL);
- static int __init my_driver_init(void) {
- int ret;
- ret = driver_register(&virtual_driver);
- if(ret)
- return ret;
- if(driver_create_file(&virtual_driver,&driver_attr_c))
- printk(KERN_NOTICE"unable to create author attr\n");
- printk("driver register success\n");
- return ret;
- }
- static void __exit my_driver_exit(void) {
- driver_unregister(&virtual_driver);
- printk("driver unregister success\n");
- }
- module_init(my_driver_init);
- module_exit(my_driver_exit);
- MODULE_AUTHOR("MANGO");
- MODULE_LICENSE("Dual BSD/GPL")
编译完后生成device.ko,加载后得到如下输出:
该device指定的父设备是my_busdev,则应该对应目录为:/sys/devices/my_busdev/mytest
执行cat c,可以看到如下输出:
三个都加载,由于driver和device名字一样,会匹配上,如下图:
此时再看bus下,文件结构如下:
会发现依附于virtual_bus总线的device和driver通过总线match起来,且都建立了相应的连接文件。
device_driver和device分别表示驱动和设备,这两者必须依附于一条总线,因此都包含了struct bus_type指针。在Linux内核中,设备和驱动程序是分开注册的。bus_type的match成员函数可以将两者捆绑在一起。
总线、驱动和设备最终会落实为sysfs中的1个目录,总线、设备和驱动中的各个attribute则直接落实为sysfs中的1个文件,attribute会伴随着show和store函数,分别用于读和写该attribute对应的sysfs文件结点。
事实上,udev规则中个信息的来源实际上就是bus_type,device_driver,device以及attribute等所对应的文件节点。
类
一个设备类描述了一种设备类型,类是一个设备的高层视图,几乎所有的类都显示在/sys/class目录中。一个例外是块设备。出于历史原因,它们出现在/sys/block下。
每个类都需要一个唯一的名字,它将显示在/sys/class中。
注册函数:int class_register(struct class *cls);
删除函数:void class_unregister(struct class *cls);
上一篇:1.the linux device model--kobject kset
下一篇:没有了
- linux 常见服务端口
- 【ROOTFS搭建】busybox的httpd...
- xmanager 2.0 for linux配置
- 什么是shell
- linux socket的bug??
- 现在的博客积分不会更新了吗?...
- shell怎么读取网页内容...
- ssh等待连接的超时问题...
- curl: (56) Recv failure: Con...
- CACTI 不能安装WINE,怎么办?...
- 2.the linux device model--bus device driver
- linux bus driver device
- linux-bus,device,driver,class
- linux-bus,device,driver,class
- linux内核 bus driver device
- The Linux device model
- bus,device和driver
- bus device driver
- linux设备模型bus,device,driver
- linux设备模型bus,device,driver
- linux 驱动 device,driver ,bus 关系
- LINUX设备模型BUS,DEVICE,DRIVER
- LINUX设备模型BUS,DEVICE,DRIVER
- linux设备模型bus,device,driver
- linux设备模型bus,device,driver
- LINUX设备模型BUS,DEVICE,DRIVER
- linux bus driver device 三者关系
- bus, device, driver之间关系
- linux class device
- linux device注册
- 学习git笔记,git,最强大的版本管理工具,没有之一。
- 模电的一些零碎问题,不定期更新
- 1.the linux device model--kobject kset
- 2.the linux device model--bus device driver
- LCS LIS LCIS 字符串编辑距离 专题
- python多线程编程(五)
- 最小区间
- 2014秋C++第10周项目2参考-M$pszi$y是嘛意思
- hdu 5086 Revenge of Segment Tree(BestCoder Round #16)
- 推荐!国外程序员整理的 C++ 资源大全
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- Eclipse中删除工作空间