Linux总线设备驱动模型学习
2015-06-27 13:31
549 查看
Linux总线驱动模型主要在2.6以后内核提出
功能:主要对热插拔、跨平台移植性的要求支持
当外部设备接入总线后,总线会与挂载到总线上的每个驱动一一进行匹配,如果匹配上就调用被匹配上的驱动。
Linux内核中,总线由bos_type结构表示,定义在<linux/device.h>
struct bus_type
{
const
char *name;
总线名称
int
(*match)(struct device*dev,stuuctdevice_driver*drv);驱动与设备的匹配函数
......
}
int (*match)(structdevice*dev,stuuctdevice_driver*drv)
当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非0.
总线的注册使用如下函数:
bus_register(struct bus_type*bus)
若成功,新的总线将被添加进系统,并可在/sys/bus下看到相应的目录。
/sys/bus目录下面存放的是总线文件
在相应总线文件里面存放有devices、drivers两个文件
devices文件存放挂载到此总线上的设备
drivers文件存放挂载到此总线上的驱动
总线的注销使用:
void bus_unregister(structbus_type*bus)
Linux内核中,驱动由device_driver结构体表示
struct device_driver
{
const
char *name;
驱动名称
struct
bus_type *bus;驱动程序所在的总线
int
(*probe)(struct device*dev);当总线上的设备与此驱动匹配上就调用此函数,处理匹配上的设备
......
}
驱动的注册使用如下函数:
int driver_register(structdevice_driver*drv)
驱动的注销使用:
void driver_uinregister(structdevice_driver*drv)
Linux内核中,设备由struct device结构表示
struct device
{
const
char *init_name;设备的名字
struct
bus tpye
*bus; 设备所在的总线
.......
}
当给init_name赋值后内核会把init_name的值赋给dev->kobj.name变量,并且把init_name赋值为NULL,所以在match函数中要使用dev->kobj.name与驱动名匹配
设备的注册使用如下函数
int device_register(structdevice*dev)
设备的注销使用
void device_unregister(structdevice*dev)
挂载到同一总线的设备名与驱动名需要一样,才能使用(*match)(structdevice*dev,stuuctdevice_driver*drv)函数通过通过匹配他们的名字匹配上
虚拟设备一般使用名字匹配
USB等设备使用设备特定硬件ID匹配
bus.c:
device.c:
driver.c:
功能:主要对热插拔、跨平台移植性的要求支持
当外部设备接入总线后,总线会与挂载到总线上的每个驱动一一进行匹配,如果匹配上就调用被匹配上的驱动。
Linux内核中,总线由bos_type结构表示,定义在<linux/device.h>
struct bus_type
{
const
char *name;
总线名称
int
(*match)(struct device*dev,stuuctdevice_driver*drv);驱动与设备的匹配函数
......
}
int (*match)(structdevice*dev,stuuctdevice_driver*drv)
当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非0.
总线的注册使用如下函数:
bus_register(struct bus_type*bus)
若成功,新的总线将被添加进系统,并可在/sys/bus下看到相应的目录。
/sys/bus目录下面存放的是总线文件
在相应总线文件里面存放有devices、drivers两个文件
devices文件存放挂载到此总线上的设备
drivers文件存放挂载到此总线上的驱动
总线的注销使用:
void bus_unregister(structbus_type*bus)
Linux内核中,驱动由device_driver结构体表示
struct device_driver
{
const
char *name;
驱动名称
struct
bus_type *bus;驱动程序所在的总线
int
(*probe)(struct device*dev);当总线上的设备与此驱动匹配上就调用此函数,处理匹配上的设备
......
}
驱动的注册使用如下函数:
int driver_register(structdevice_driver*drv)
驱动的注销使用:
void driver_uinregister(structdevice_driver*drv)
Linux内核中,设备由struct device结构表示
struct device
{
const
char *init_name;设备的名字
struct
bus tpye
*bus; 设备所在的总线
.......
}
当给init_name赋值后内核会把init_name的值赋给dev->kobj.name变量,并且把init_name赋值为NULL,所以在match函数中要使用dev->kobj.name与驱动名匹配
设备的注册使用如下函数
int device_register(structdevice*dev)
设备的注销使用
void device_unregister(structdevice*dev)
挂载到同一总线的设备名与驱动名需要一样,才能使用(*match)(structdevice*dev,stuuctdevice_driver*drv)函数通过通过匹配他们的名字匹配上
虚拟设备一般使用名字匹配
USB等设备使用设备特定硬件ID匹配
bus.c:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> /* 需要遵循GPL协议才能调用bus_register、bus_unregister函数 */ MODULE_LICENSE("GPL"); /* 驱动与设备的匹配函数: 当给init_name赋值后内核会把init_name的值赋给dev->kobj.name 并且把init_name赋值为NULL,所以在match函数中要使用dev->kobj.name 与驱动名匹配*/ int my_match(struct device *dev, struct device_driver *drv) { return !strncmp(dev->kobj.name,drv->name,strlen(drv->name)); } /* 总线结构体 */ struct bus_type my_bus_type = { .name = "my_bus", .match = my_match, }; //输出此符号,让别的模块调用 EXPORT_SYMBOL(my_bus_type); int my_bus_init() { int ret; ret = bus_register(&my_bus_type); return ret; } void my_bus_exit() { 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> MODULE_LICENSE("GPL"); extern struct bus_type my_bus_type; /* 当给init_name赋值后内核会把init_name的值赋给dev->kobj.name 并且把init_name赋值为NULL,所以在match函数中要使用dev->kobj.name 与驱动名匹配*/ struct device my_dev = { .init_name = "my_dev", .bus = &my_bus_type, }; int my_device_init() { int ret; ret = device_register(&my_dev); return ret; } void my_device_exit() { 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> MODULE_LICENSE("GPL"); //extern指明后面的变量来自外部 extern struct bus_type my_bus_type; //调用bus.c文件中声明过的总线变量 int my_probe(struct device *dev) { printk("driver found the device it can handle!\n"); //硬件初始化。。。 return 0; } struct device_driver my_driver = { .name = "my_dev", .bus = &my_bus_type, .probe = my_probe, //当设备与驱动匹配上后,调用此函数 }; int my_driver_init() { int ret; ret = driver_register(&my_driver); return ret; } void my_driver_exit() { driver_unregister(&my_driver); } module_init(my_driver_init); module_exit(my_driver_exit);
相关文章推荐
- 实现虚拟机VMware上linux与windows互相复制与粘贴
- MBR、GRUB、Linux启动相关知识
- Linux中的常用内存问题检测工具
- Linux---修改用户的密码
- 在linux下利用nohup来后台运行java程序
- linux6.4DNS辅助
- Linux---如何将普通用户加入root用户组
- redhat 替换centos yum 后,安装wireshark 无法使用
- 2015年CSDN对嵌入式Linux专家,100ask创始人韦东山的采访
- 最近在学习Linux,下面是一些学习笔记,以后会不定期更新,以此做总结.
- 作为一个新人,怎样学习嵌入式Linux?(转自韦东山)
- linux命令eval的用法
- Linux_5.2_线程互斥
- 用vs2013+velt-0.1.4进行嵌入式开发 进行海思平台 UBOOT 开发 分类: arm-linux-Ubuntu Windows-嵌入式 2015-06-27 11:59 393人阅读 评论(0) 收藏
- Linux学习笔记
- Linux 下编译并安装配置 Qt (完整版)
- Linux操作系统及ubuntu相关
- Linux入门篇之三:虚拟机的快照和克隆
- Linux启动与禁止SSH用户及IP的登录
- Linux下Telnet、FTP、SSH、SFTP、SCP