bus(总线)、driver(驱动)、device(设备)

一条bus上挂着许多device,而device需要driver才能工作。内核有注册device和注册driver的概念。注册device只是将deivce添加到内核中,该设备还不能工作。而注册driver,就是在对应的bus上找到device,从而调用driver的probe函数进行初始化,而后继续其它的事情。

device和driver通过某些方式匹配,就能正常工作。比如platform设备根据name来匹配的,PCI设备根据ID匹配。所以看到很多内核代码在定义platform_device时指定name,而在定义platform_driver时指定driver成员的name,因为只有这样两者才能匹配。一般地,发行版本的Linux系统都带有很多驱动。如前段时间研究WIFI,将Intel无线网卡和atheros无线网卡插到安装有发行版本的系统的设备上,就可以正常工作。

在/sys/bus/目录下有当前系统各种bus。比如i2c总线、PCI总线、SPI总线、platform总线。每种bus目录均有device和driver,在其中列出该总线上所有的设备和对应的驱动。比如platform设备、驱动分别在/sys/bus/platform/devices和/sys/bus/platform/drivers这两个目录。

 

设备挂载到总线上,当加载驱动时,驱动就从总线上找到自己对应的设备。

或者先把驱动加载上,来了一个设备就去总线找驱动。

 

 
创建设备实例:将设备device.c,编译成模块,以动态加载的方式加载到内核。会发现在sys/bus/my_bus/devices/目录下有一个my_dev设备,查看属性,它是挂在/sys/devices/my_bus0/my_dev目录下,至此添加设备成功。

#include #include #include #include #include extern struct device my_bus; //这里用到了总线设备中定义的结构体

extern struct bus_type my_bus_type;
static int my_device_release() {
return 0;
}
struct device my_dev={ //创建设备属性
.bus = &my_bus_type,//定义总线类型
.parent = &my_bus,//定义my_dev的父设备。
.release = my_device_release,
};
static ssize_t mydev_show(struct device *dev, char *buf) {
return sprintf(buf, "%s\n", "This is my device!");
}
static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);
static int __init my_device_init(void){
int ret;
strncpy(my_dev.bus_id, "my_dev", BUS_ID_SIZE); //初始化设备

ret = device_register(&my_dev); //注册设备

if (ret)
printk("device register!\n");
device_create_file(&my_dev, &dev_attr_dev); //创建设备文件
return ret;
}
static void __exit my_device_exit(void) {
device_unregister(&my_dev);//卸载设备

}
module_init(my_device_init);
module_exit(my_device_exit);
MODULE_AUTHOR("Fany");
MODULE_LICENSE("GPL");

驱动实例:当加载驱动程序时,终端界面上打印Driver found device!
说明驱动找到了匹配的设备,看到打印这个时,想到在windows下插U盘,立马弹出“发现可移动设备”,有点相像!
再看看相应的目录:/sys/bus/my_bus/drivers/,多了一个my_dev。

#include 
#include 
#include 
#include 
#include 
extern struct bus_type my_bus_type;
static int my_probe(struct device *dev) {
printk("Driver found device!\n");
return 0;
};
static int my_remove(struct device *dev) {
printk("Driver unpluged!\n");
return 0;
};
struct device_driver my_driver = {
.name = "my_dev",
.bus = &my_bus_type,
.probe = my_probe,
.remove = my_remove,
};
//定义设备驱动属性

static ssize_t my_driver_show(struct device_driver *driver, char *buf) {
return sprintf(buf, "%s\n", "This is my driver!");
};
static DRIVER_ATTR(drv, S_IRUGO, my_driver_show, NULL);
static int __init my_driver_init(void){
int ret;
//注册设备驱动

ret = driver_register(&my_driver);
if(ret)
printk("driver_register failed!\n");
//创建设备驱动属性

ret = driver_create_file(&my_driver, &driver_attr_drv);
if(ret)
printk("create_driver_file failed!\n");

return ret;
}
static void __exit my_driver_exit(void){
driver_unregister(&my_driver);//注销设备驱动

}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_AUTHOR("Fany");
MODULE_LICENSE("GPL");