总线设备驱动模型

——————/总线
struct bus_type
	const char	*name;	//总线名称
	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, struct kobj_uevent_env *env);
总线注册int bus_register(struct bus_type *bus),若成功可在sysfs的/sys/bus下看到
总线删除void bus_unregister(struct bus_type *bus)
match当一新设备或驱动被添加到总线,该方法被调用,用于判断指定驱动是否能处理指定设备,若可以返回非零值
uevent为用户空间产生热插拔事件之前,该方法允许总线添加环境变量
struct bus_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct bus_type *bus, char *buf);
	ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
};

int bus_create_file(struct bus_type *bus,struct bus_attribute *attr)创建属性
void bus_remove_file(struct bus_type*bus, struct bus_attribute *attr)删除属性
——————/设备
struct device
	struct kobject kobj;
	const char		*init_name;
	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this device */
	void		*platform_data;

int device_register(struct device *dev)注册设备
void 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);
};

int device_create_file(struct device*device, struct device_attribute * entry)创建属性
void device_remove_file(struct device *dev, struct device_attribute * attr)删除属性
——————/驱动
struct device_driver
	const char		*name;	//驱动程序名字
	struct bus_type		*bus;	//驱动所在总线
	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);  //所能处理设备被删除

int driver_register(struct device_driver *drv)注册驱动
void driver_unregister(struct device_driver *drv)注销驱动

struct driver_attribute {	//驱动属性
	struct attribute attr;
	ssize_t (*show)(struct device_driver *driver, char *buf);
	ssize_t (*store)(struct device_driver *driver, const char *buf,size_t count);
};

int driver_create_file(struct device_driver * drv,struct driver_attribute * attr)创建属性
void driver_remove_file(struct device_driver * drv,struct driver_attribute * attr)删除属性

——————/bus.c

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

static int my_match(struct device *dev, struct device_driver *driver)
{
	return !strncmp(dev->kobj.name, driver->name,strlen(driver->name));
}

struct bus_type my_bus_type = {
	.name = "my_bus",
	.match = my_match,
};

static ssize_t show_bus(struct bus_type *bus, char *buf)
{
	return sprintf(buf,"%s", "lyl_bus\n");
}

static BUS_ATTR(lyl, S_IRUGO, show_bus, NULL);
static int my_bus_init(void)
{
	bus_register(&my_bus_type);
	bus_create_file(&my_bus_type, &bus_attr_lyl);
	return 0;
}

static void my_bus_exit(void)
{
	bus_unregister(&my_bus_type);
}

EXPORT_SYMBOL(my_bus_type);

module_init(my_bus_init);
module_exit(my_bus_exit);
MODULE_LICENSE("GPL");
——————/device.c
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

extern struct bus_type my_bus_type;

static void my_dev_release(struct device *dev)
{ 
	printk("my_dev_release\n");
}

struct device my_dev = {
	.init_name="lyl_dev",
	.bus = &my_bus_type,
	.release = my_dev_release,
};

static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%s", "This is my device!\n");
}

static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);
static int my_device_init(void)
{
	device_register(&my_dev);
	device_create_file(&my_dev, &dev_attr_dev);
	return 0;	
}

static void my_device_exit(void)
{
	device_unregister(&my_dev);
}
——————/driver.c
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

extern struct bus_type my_bus_type;

static int my_probe(struct device *dev)
{
	printk("my_probe\n");
	return 0;
}

static int my_remove(struct device *dev)
{
	printk("my_remove\n");
	return 0;
}

struct device_driver my_driver = {
	.name = "lyl_dev",
	.bus = &my_bus_type,
	.probe = my_probe,
	.remove	= my_remove,
};

static ssize_t mydriver_show(struct device_driver *driver, char *buf)
{
	return sprintf(buf, "%s", "This is my driver!\n");
}

static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);
static int my_driver_init(void)
{
	driver_register(&my_driver);
	driver_create_file(&my_driver, &driver_attr_drv);
	return 0;
}

static void my_driver_exit(void)
{
	driver_unregister(&my_driver);
}
——————/
/12 # insmod bus.ko
/12 # cd /sys/bus/my_bus/
/sys/bus/my_bus # ls
devices drivers_autoprobe lyl
drivers drivers_probe uevent
/sys/bus/my_bus # cat lyl
lyl_bus

/sys/bus/my_bus # insmod /12/device.ko
/sys/bus/my_bus # cd devices/lyl_dev/ //进到/sys/devices/lyl_dev,链接
/sys/devices/lyl_dev # ls
dev power subsystem uevent
/sys/devices/lyl_dev # cat dev
This is my device!

/sys/bus/my_bus # insmod /12/driver.ko
my_probe
/sys/bus/my_bus # cd drivers/lyl_dev/
/sys/bus/my_bus/drivers/lyl_dev # ls
bind drv lyl_dev uevent unbind
/sys/bus/my_bus/drivers/lyl_dev # cat drv
This is my driver!

/sys/bus/my_bus # rmmod device
my_remove
my_dev_release
/sys/bus/my_bus # rmmod driver
/sys/bus/my_bus # rmmod bus
——————/注意
若只去掉:EXPORT_SYMBOL(my_bus_type);
/12 # insmod bus.ko
/12 # insmod driver.ko
driver: Unknown symbol my_bus_type (err 0)
insmod: can't insert 'driver.ko': unknown symbol in module or invalid parameter

若只去掉:extern struct bus_type my_bus_type; //driver.c
root@lyl:/home/test# make
error: 'my_bus_type' undeclared here
——————/实验
bus.c中定义函数my_print,driver.c中extern并在入口函数中调用:
void my_print(void)
{
printk("my_print\n");
}
/12 # insmod bus.ko
/12 # insmod driver.ko
Unknown symbol my_print

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值