前面的几个驱动代码软件和硬件都是夹杂在一起的,这样就会使得驱动的复用性比较低。Bus是链接处理器和其他设备之间的通道。内核规定,系统中的每个设备都要连接在一个Bus上,这个Bus可以是一个内部Bus、虚拟Bus或者Platform Bus。前面的驱动通过引入驱动总线,将硬件相关与软件相关的代码进行分离,将结构体device关联硬件相关代码,将driver_devices关联软件代码,通过设置match匹配规则,使用bus_type对设备进行统一管理。
这个函数实在linux启动的时候就自动执行的,主要是建立Linux设备模型总线部分的顶级节点。buses_init函数建立了/sys/bus这个顶级容器节点,该节点是Linux内核中所有总线类型的父节点。
原型:int bus_register(struct bus_type *bus)
作用:(添加一个新的总线类型)
在/sys/bus下建立xbus目录项,并创建属性文件
在/sys/bus/xbus下建立devices目录项,并创建属性文件
在/sys/bus/xbus下建立drivers目录项,并创建属性文件
初始化 priv->klist_devices链表头
初始化priv->klist_drivers链表头
原型:int device_register(struct device *dev)
作用:(添加设备,关联硬件相关代码)
在/sys/bus/xbus/devices下建立yyy目录项
加入bus-> priv->devices_kset链表
加入bus-> priv->klist_devices链表
遍历bus-> priv->klist_drivers,执行bus->match()寻找合适的drv
dev关联driv,执行drv->probe()
原型:int driver_register(struct device_driver *drv)
作用:(添加驱动,关联软件相关代码)
在/sys/bus/xbus/drivers下建立zzz目录项
加入bus-> priv->drivers_kset链表
加入bus-> priv->klist_drivers链表
遍历bus-> priv->klist_klist_devices链表,执行bus->match()寻找合适的dev
dev关联dev,执行drv->probe()
xbus.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
/*
*本文件主要是添加一个新的总线类型
*/
/*
*match 规则
*/
int match(struct device *dev, struct device_driver *drv)
{
if(strncmp(dev_name(dev), drv->name, strlen(drv->name)))
{
printk(KERN_ERR"xBus match failed!\r\n");
return 0;
}
printk(KERN_ERR"xBus match successed!\r\n");
return 1;
}
/*初始化设备*/
static struct bus_type xBus =
{
.name = "xBus",
.match = match,
};
static int __init xBusInit(void)
{
printk(KERN_ERR"Enter xBus init functions\r\n");
if(bus_register(&xBus))
{
printk(KERN_ERR"Enter xBus init failed!\r\n");
return -1;
}
return 0;
}
static void __exit xBusExit(void)
{
printk(KERN_ERR"Exit xBus init functions\r\n");
return ;
}
/*声明外部调用*/
EXPORT_SYMBOL (xBus);
/*声明函数*/
module_init(xBusInit);
module_exit(xBusExit);
/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xBus module!");
MODULE_ALIAS("xBus_module");
xdev.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
extern struct bus_type xBus;
/**/
void xDevRelease(struct device *dev)
{
printk("%s-%s\n", __FILE__, __func__);
}
/*
*本文件主要是添加一个新的设备(硬件相关)
*/
static struct device dev =
{
.init_name = "xbus_test",
.bus = &xBus,
.release = xDevRelease,
};
/*初始化设备*/
static int __init xDevInit(void)
{
printk(KERN_ERR"Init xDev init functions\r\n");
if(device_register(&dev))
{
printk(KERN_ERR"Init xDev init failed!\r\n");
return -1;
}
return 0;
}
static void __exit xDevExit(void)
{
printk(KERN_ERR"Exit xDev init functions\r\n");
return ;
}
/*声明函数*/
module_init(xDevInit);
module_exit(xDevExit);
/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xDev module!");
MODULE_ALIAS("xDev_module");
xdrv.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
extern struct bus_type xBus;
int xDrvProbe(struct device *dev)
{
printk(KERN_ERR"Match success!\r\n");
return 0;
}
int xDrvRemove(struct device *dev)
{
printk(KERN_ERR"Close xbus_test derver!\r\n");
return 0;
}
/*
*本文件主要是添加一个新的设备(硬件相关)
*/
static struct device_driver xDrv =
{
.name = "xbus_test",
.bus = &xBus,
//当驱动和设备匹配成功之后,便会执行驱动的probe函数
.probe = xDrvProbe,
//当注销驱动时,需要关闭物理设备的某些功能等
.remove = xDrvRemove,
};
/*初始化设备*/
static int __init xDrvInit(void)
{
printk(KERN_ERR"Init xDrv init functions\r\n");
if(driver_register(&xDrv))
{
printk(KERN_ERR"Init xDrv init failed!\r\n");
return -1;
}
printk(KERN_ERR"Init xDrv functions success!\r\n");
return 0;
}
static void __exit xDrvExit(void)
{
printk(KERN_ERR"Exit xDrv init functions\r\n");
return ;
}
/*声明函数*/
module_init(xDrvInit);
module_exit(xDrvExit);
/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xDrv module!");
MODULE_ALIAS("xDrv_module");
Makefile
KERNEL_DIR=../../ebf_linux_kernel/build_image/build/
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH CROSS_COMPILE
obj-m := xbus.o xdev.o xdrv.o
all:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
.PHONE:clean copy
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
copy:
sudo cp *.ko /home/dragon/nfsshare
编译代码
make
将ko文件复制到共享文件夹
make copy
打开开发板
登陆开发板
连接到远程文件夹(nfs)
sudo mount -t nfs 192.168.3.41:/home/dragon/nfsshare /mnt
加载模块(注意顺序)
命令
sudo insmod /mnt/xbus.ko
现象
xbus: loading out-of-tree module taints kernel.
Enter xBus init functions
命令
sudo insmod /mnt/xdev.ko
现象
Init xDev init functions
命令
sudo insmod /mnt/xdrv.ko
现象
[ 94.381356] Init xDrv init functions
[ 94.391380] xBus match successed!
[ 94.398011] Match success!
[ 94.409179] Init xDrv functions success!