linux平台设备驱动模型是什么意思,Linux设备驱动模型之我理解

点击(此处)折叠或打开

/* my_bus.c   */

#include

#include

#include

#include

#include

#include "my_bus.h"

MODULE_LICENSE("Dual BSD/GPL");

#define MYBUS "mybus: "

#define PRINT(x...) printk(KERN_ALERT MYBUS x);

static char *Version = "$Revision: 1.9 $";

static ssize_t show_bus_version(struct bus_type *bus, char *buf)

{

PRINT("%s\n", __func__);

return snprintf(buf, PAGE_SIZE, "my_bus: %s\n", Version);

}

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);

static void my_bus_release(struct device *dev)

{

PRINT("%s\n", __func__);

}

static int my_bus_match(struct device *dev, struct device_driver *drv)

{

struct my_device *device = to_my_device(dev);

PRINT("%s\n", __func__);

return !strncmp(device->name, drv->name, strlen(drv->name));

}

static int my_bus_hotplug(struct device *dev, struct kobj_uevent_env *env){

PRINT("%s\n", __func__);

return 0;

}

struct bus_type my_bus_type = {

.name = "my_bus",

.match = my_bus_match,

.uevent = my_bus_hotplug

};

static struct device my_bus = {

.init_name = "my_bus0",

.release = my_bus_release

};

/* interface to device. */

int register_my_device(struct my_device *device)

{

PRINT("%s\n", __func__);

device->device.bus = &my_bus_type;

device->device.parent = &my_bus;

device->device.release = my_bus_release;

//strncpy(device->device.bus_id, device->name, BUS_ID_SIZE);

return device_register(&device->device);

}

EXPORT_SYMBOL(register_my_device);

void unregister_my_device(struct my_device *device)

{

PRINT("%s\n", __func__);

device_unregister(&device->device);

}

EXPORT_SYMBOL(unregister_my_device);

static ssize_t show_version(struct device_driver *driver, char *buf)

{

struct my_driver *drv = to_my_driver(driver);

PRINT("%s\n", __func__);

sprintf(buf, "%s\n", drv->version);

return strlen(buf);

}

/* interface to driver. */

int register_my_driver(struct my_driver *driver)

{

int ret = 0;

PRINT("%s\n", __func__);

driver->driver.bus = &my_bus_type;

ret = driver_register(&driver->driver);

if (ret) {

PRINT("%s, driver_register %s failed!!!\n", __func__, driver->driver.name);

return ret;

}

driver->version_attr.attr.name = "version";

//driver->version_attr.attr.owner = driver->module;

driver->version_attr.attr.mode = S_IRUGO;

driver->version_attr.show = show_version;

return driver_create_file(&driver->driver, &driver->version_attr);

}

EXPORT_SYMBOL(register_my_driver);

void unregister_my_driver(struct my_driver *driver)

{

PRINT("%s\n", __func__);

driver_unregister(&driver->driver);

}

EXPORT_SYMBOL(unregister_my_driver);

static int __init my_bus_init(void)

{

int ret = 0;

ret = bus_register(&my_bus_type);

if (ret) {

PRINT("%s, bus_register failed!\n", __func__);

goto bus_register_failed;

}

ret = bus_create_file(&my_bus_type, &bus_attr_version);

if (ret) {

PRINT("%s, bus_create_file failure...!\n", __func__);

goto bus_create_file_failed;

}

ret = device_register(&my_bus);

if (ret) {

PRINT("%s, device_register failure...!\n", __func__);

goto device_register_failed;

}

PRINT("%s, bus & device register succeed!\n", __func__);

return 0;

device_register_failed:

bus_create_file_failed:

bus_unregister(&my_bus_type);

bus_register_failed:

return ret;

}

static void __exit my_bus_exit(void)

{

PRINT("%s!\n", __func__);

device_unregister(&my_bus);

bus_unregister(&my_bus_type);

}

module_init(my_bus_init);

module_exit(my_bus_exit);

my_bus.c 是实现 my_bus 的主要文件. 其实一条总线, 在 Linux 设备驱动模型中, 它也是一个设备. 所以, 需要声明 my_bus_type 的同时, 还要声明 my_bus 这个设备.(注:C语言中,非导出符号在文件中声明时用static标明.所以, 在my_bus.c中, 你将看到大多数的函数都是static.)

注册 my_bus 的步骤.

1. 声明my_bus_type, 类型为 bus_type. 作为总线.

点击(此处)折叠或打开

struct bus_type my_bus_type = {

.name    = "my_bus",      //总线名称.

.match   = my_bus_match,  //用来匹配设备和驱动的函数.

.uevent  = my_bus_hotplug //用来发送uevent到用户空间.

};2. 声明my_bus,类型为 struct device, 因为my_bus也是一种设备.

点击(此处)折叠或打开

static struct device my_bus = {

.init_name = "my_bus0", //my_bus设备的名称.在device_add函数里会将init_name复制到kobject中.

.release = my_bus_release //取消注册的设备的时候要调用的函数.

};

3. 调用 bus_register(&my_bus_type) 将 my_bus_type 这个总线类型注册到系统.

4. 调用 device_register(&my_bus) 将总线设备注册到系统.

(步骤3和4都在my_bus_init函数中.)

点击(此处)折叠或打开

static int __init my_bus_init(void)

{

int ret = 0;

ret = bus_register(&my_bus_type); //注册my_bus_type到Linux设备驱动模型中.

if (ret) {

PRINT("%s, bus_register failed!\n", __func__);

goto bus_register_failed;

}

ret = bus_create_file(&my_bus_type, &bus_attr_version);//创建my_bus的一个属性.在sysfs中体现.

if (ret) {

PRINT("%s, bus_create_file failure...!\n", __func__);

goto bus_create_file_failed;

}

ret = device_register(&my_bus); //注册my_bus到Linux设备驱动模型中.

if (ret) {

PRINT("%s, device_register failure...!\n", __func__);

goto device_register_failed;

}

PRINT("%s, bus & device register succeed!\n", __func__);

return 0;

device_register_failed:

bus_create_file_failed:

bus_unregister(&my_bus_type);

bus_register_failed:

return ret;

}上面四个步骤, 就将一条总线注册到 Linux设备驱动模型中.

编译并将 my_bus.ko 插入到到系统后,

可以通过命令 ls /sys/bus/  会看到 my_bus 文件夹.

通过命令 ls /sys/device/ 会看到 my_bus0 文件夹.

其实, 对于 Linux 设备驱动模型而言, 它管理的, 是 bus_type, device 和 device_driver 三大主体. 譬如我这里的my_bus, my_device, my_driver 都是 bus_type, device, device_driver 的拓展, 都离不开 bus_type, device, device_driver 这三个主体. 所以, 这也就是为什么对应的数据结构中间都要包含它们.(my_bus_type 本身就是 bus_type 类型.)

取消 my_bus 这条总线, 有两个步骤:

1. 取消 my_bus 设备的注册.

2. 取消 my_bus_type 的注册.

步骤1和2都是在 my_bus_exit 函数中.

点击(此处)折叠或打开

static void __exit my_bus_exit(void)

{

PRINT("%s!\n", __func__);

device_unregister(&my_bus);

bus_unregister(&my_bus_type);

}

驱动的加载和卸载都是 module_init 和 module_exit 来实现的.

module_init(my_bus_init);

module_exit(my_bus_exit);

总线上的驱动和设备的匹配函数如下. 就是通过简单的驱动的名称和设备的名称一致即可.(Linux内核很多都是这样实现的.)

点击(此处)折叠或打开

static int my_bus_match(struct device *dev, struct device_driver *drv)

{

struct my_device *device = to_my_device(dev);

PRINT("%s\n", __func__);

return !strncmp(device->name, drv->name, strlen(drv->name));

}

注册与卸载设备:

在 my_bus 上注册设备的过程, 就是将 my_device 结构体中 device 结构体进行赋值:

1. bus_type 成员设置为 my_bus_type

2. parent 设置为 my_bus.

3. release 函数设置为 my_bus_release.

然后调用 device_register 函数将 my_device 中的 device 结构加入到 Linux 设备驱动模型的管理中.

点击(此处)折叠或打开

int register_my_device(struct my_device *device)

{

PRINT("%s\n", __func__);

device->device.bus = &my_bus_type;

device->device.parent = &my_bus;

device->device.release = my_bus_release;

//strncpy(device->device.bus_id, device->name, BUS_ID_SIZE);

return device_register(&device->device);

}

EXPORT_SYMBOL(register_my_device);

卸载 my_bus 上的 my_device 过程:

1. 调用 device_unregister 函数将 my_device 中的 device 结构从 Linux 设备驱动模型中移除.

点击(此处)折叠或打开

void unregister_my_device(struct my_device *device)

{

PRINT("%s\n", __func__);

device_unregister(&device->device);

}

EXPORT_SYMBOL(unregister_my_device);

注册与卸载驱动:

在my_bus总线上注册驱动的过程, 也就是对 my_driver 中 device_driver 的处理过程.

1. 设置 device_driver 的成员 bus 为 my_bus_type.

2. 调用 driver_register 函数, 将 device_driver 添加到 Linux 设备驱动模型中管理.

点击(此处)折叠或打开

int register_my_driver(struct my_driver *driver)

{

int ret = 0;

PRINT("%s\n", __func__);

driver->driver.bus = &my_bus_type;

ret = driver_register(&driver->driver);

if (ret) {

PRINT("%s, driver_register %s failed!!!\n", __func__, driver->driver.name);

return ret;

}

driver->version_attr.attr.name = "version";

//driver->version_attr.attr.owner = driver->module;

driver->version_attr.attr.mode = S_IRUGO;

driver->version_attr.show = show_version;

return driver_create_file(&driver->driver, &driver->version_attr);

}

EXPORT_SYMBOL(register_my_driver);

在my_bus总线上卸载驱动的过程, 也是对 my_driver 中 device_driver 的处理过程.

1. 调用driver_unregister函数将 device_driver 从 Linux 设备驱动模型中移除.

点击(此处)折叠或打开

void unregister_my_driver(struct my_driver *driver)

{

PRINT("%s\n", __func__);

driver_unregister(&driver->driver);

}

EXPORT_SYMBOL(unregister_my_driver);

EXPORT_SYMBOL 是用来导出符号的. 用 EXPORT_SYMBOL 导出的符号, 其他模块也可以使用.

属性(Attribute)

在 Linux 设备驱动模型中, 总线, 设备, 驱动的特性, 都是通过属性这一工具来呈现在 sysfs 文件系统中. 导出到用户空间的.

1. 声明一个属性 bus_attr_version.

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);

在内核源码中, 会看到, BUS_ATTR 是一个宏, 基于 __ATTR 这个宏而来的, 只是在 __ATTR 宏的基础上, 赋予一些初值.BUS_ATTR 宏如下:

#define BUS_ATTR(_name, _mode, _show, _store)    \

struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

其中:

_mode 是属性在 sysfs 中对应文件的访问权限.

_show 是读取 sysfs 中对应文件时调用的方法.

_store 是写 sysfs 中对应的文件触发的方法.

2. 将属性和bus_type挂接. 那么, Linux 设备驱动模型会在 sysfs 文件系统下生成对应的文件.

__________________________________________________________________________________________

下面是测试 my_bus 总线使用的 驱动和设备的代码.

我的设备 my_device.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值