06_平台总线匹配规则,自己搭建总线xbus

总结

bus_register()
自己创建平台总线 /sys/bux/xxx
device_register()
对平台总线加入dev /sys/bus/xxx/dev
driver_register()
对平台总线加入drv /sys/bus/xxx/drv
两个相匹配的时候 直接调用drv->probe 函数 进行基本的class_create() device_create()等
创建设备文件 和设备节点
在这里插入图片描述

代码实例

xubs.cxdev.c

#include <linux/init.h>
#include <linux/module.h>

#include <linux/device.h>

int xbus_match(struct device *dev, struct device_driver *drv)
{

	printk(KERN_ALERT "%s-%s\n", __FILE__, __func__);
	if (!strncmp(dev_name(dev), drv->name, strlen(drv->name))) {
		printk(KERN_ALERT "dev & drv match\n");
		return 1;
	}
	return 0;

}
static struct bus_type xbus = {
	.name = "xbus",
	.match = xbus_match,
};

EXPORT_SYMBOL(xbus);

static __init int xbus_init(void)
{
    int ret;
	printk(KERN_ALERT "xbus init\n");
	ret = bus_register(&xbus);
    if(ret != 0){
         return -1;
    }
	return 0;
}

module_init(xbus_init);

static __exit void xbus_exit(void)
{
	printk(KERN_ALERT "xbus exit\n");
	bus_unregister(&xbus);
}

module_exit(xbus_exit);

MODULE_AUTHOR("embedfire");
MODULE_LICENSE("GPL");

xdev.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>

extern struct bus_type xbus;

void xdev_release(struct device *dev)
{
	printk(KERN_ALERT "%s-%s\n", __FILE__, __func__);
}

static struct device xdev = {
	.init_name = "xdev",
	.bus = &xbus,
	.release = xdev_release,
};

static __init int xdev_init(void)
{
    int ret;
	printk(KERN_ALERT "xdev init\n");
	ret = device_register(&xdev);
    if(ret != 0){
         return -1;
    }
       
	return 0;
}

static __exit void xdev_exit(void)
{
	printk(KERN_ALERT "xdev exit\n");
	device_unregister(&xdev);
}

module_init(xdev_init);
module_exit(xdev_exit);

MODULE_AUTHOR("embedfire");
MODULE_LICENSE("GPL");

xdrv.c

#include <linux/init.h>
#include <linux/module.h>

#include <linux/device.h>

extern struct bus_type xbus;

int xdrv_probe(struct device *dev)
{
	printk(KERN_ALERT "%s-%s\n", __FILE__, __func__);
	return 0;
}

int xdrv_remove(struct device *dev)
{
	printk(KERN_ALERT "%s-%s\n", __FILE__, __func__);
	return 0;
}

static struct device_driver xdrv = {
	.name = "xdev",
	.bus = &xbus,
	.probe = xdrv_probe,
	.remove = xdrv_remove,
};

static __init int xdrv_init(void)
{
    int ret;
	printk( KERN_ALERT"xdrv init\n");
	ret = driver_register(&xdrv);
    if(ret != 0){
         return -1;
    }
	return 0;
}

static __exit void xdrv_exit(void)
{
	printk(KERN_ALERT "xdrv exit\n");
	driver_unregister(&xdrv);
}

module_init(xdrv_init);
module_exit(xdrv_exit);

MODULE_AUTHOR("embedfire");
MODULE_LICENSE("GPL");

详细解析

自己弄一套驱动总线 xbus
match规则 找到drv 和 dev的链表头去匹配
分离的思想 也在设备驱动模型中 在sys的目录下面 有一个bus的文件夹
bus用来管理一系列的总线
在这里插入图片描述

总线初始化

/sys/bus 在linux总线初始化的时候 就有这个文件夹
后续把自己定义的总线都放在这么文件夹下

buses_init()函数 内核启动自动执行
	//创建kset=bus_kset 创建kobj=bus 和目录
	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 

自定义一个新的总线xbus
在这里插入图片描述

bus_register(struct bus_type *bus)函数  添加新的总线类型
	需要定义一个bus_type结构体并且把指针传进去 因为要创建三个目录项所以bus结构体里面有三个kobj对象
	看看bus结构体 bus_type->prive 有三个kset变量 用来满足三个目录项的要求
	因为每个目录项都要有属性文件 bus_type有三个attr_goup结构体指针
	因为要管理dev和drv结构体 所以 bus_type有两链表头
	
	
-/sys/bus下建立xbus目录项,并创建属性文件
-/sys/bus/xbus下建立devices目录项,并创建属性文件
-/sys/bus/xbus下建立drivers目录项,并创建属性文件
- 初始化 priv->klist_devices链表头
- 初始化priv->klist_drivers链表头
创建dev drv

在这里插入图片描述

设备注册
往总线的device目录里面新增目录项 
int device_register(struct device *dev)
	因为要建立新的目录项 device结构体也有kobj对象
	device对象要加入xubs的dev链表里面 所以device->p->klist进行加入
-/sys/bus/xbus/devices下建立yyy目录项
- 加入bus-> priv->devices_kset链表
- 加入bus-> priv->klist_devices链表
- 遍历bus-> priv->klist_drivers,执行bus->match()寻找合适的drv
- dev关联driv,执行drv->probe()

匹配 
	dev列表节点和drv列表节点互相搜索
	有合适的 device->driver会指向匹配到的driver结构体
	然后调用driver->probe
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值