热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

嵌入式Linuxmisc设备驱动

misc设备驱动简介那么杂项设备驱动是属于我们linux三大设备驱动的哪一项呢?由于linux驱动倾向于分层设计,所以每个具体的设备都可以找到它归属的类

misc 设备驱动简介
        那么杂项设备驱动是属于我们 linux 三大设备驱动的哪一项呢? 由于linux 驱动倾向于分层设计, 所以每个具体的设备都可以找到它归属的类型, 从而可以套到它相应的架构里面去, 我们只需要实现它最底层的那部分。 但是也有部分字符设备, 确实不知道它属于哪种类型, 一般推荐大家采用 miscdevice 的框架结构。 misc 的意思是混合的杂项的, 所以 misc 设备驱动也叫做杂项设
备驱动, 当板子上的某个设备没有办法分类时, 就可以用 misc 设备驱动。 它的注册跟使用比较的简单,所以比较适用于功能简单的设备。 正因为简单, 所以它通常嵌套在 platform 总线驱动中, 配合总线驱动达到更复杂, 多功能的效果。 杂项设备是字符设备的一种, 杂项设备可以自动生成设备节点。
        在学习 misc 设备驱动之前, 先来了解几个基础概念。
概念 1 设备节点
        我们可以启动我们的开发板, 进入到 dev 目录下, dev 目录下全部都是生成的设备节点, 如下图所示:

我们的系统里面有很多杂项设备。 我们可以输入以下命令来查看, 如下图所示:
cat /proc/misc
 

概念 2 杂项设备的优点
        杂项设备除了比字符设备代码简单, 还有别的区别吗? 所有的 misc 设备驱动的主设备号都为 10, 不同的设备使用不同的从设备号。 主设设备号相同就可以节省内核的资源, 在内核中大概可以找到 200 多处使用 miscdevice 框架结构的驱动。
概念 3 主设备号和次设备号的概念
        设备号包含主设备号和次设备号, 设备号是计算机识别设备的一种方式, 主设备号相同的就被视为同一类设备, 主设备号在 Linux 系统里面是唯一的, 次设备号不一定唯一。 主设备号可以比做成电话号码的区号。 比如北京的区号是 010, 次设备号可以比作成电话号码。
        主设备号可以通过以下命令来查看, 前面的数字就是主设备号, 如下图所示:
 cat /proc/devices

        misc 设备用 miscdevice 结构体表示, miscdevice 结构体的定义在内核源码具体定义在
include/linux/miscdevice.h 中, 内容如下:

struct miscdevice {int minor; //次设备号const char *name; //设备节点的名字const struct file_operations *fops; //文件操作集struct list_head list;struct device *parent;struct device *this_device;const struct attribute_group **groups;const char *nodename;umode_t mode;
};

        当我们创建一个 misc 设备的 miscdevice 结构体时, 需要我们指定 minor、 name 和 fops 这三个成员变量。 minor 表示次设备号, 需要用户设置, 在 Linux 内核中有一些预定义的 misc 设备的次设备号, 定义在 include/linux/miscdevice.h 文件中, 如下所示:
 

#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2 /* unused */
#define ATIXL_BUSMOUSE_MINOR 3 /* unused */
/*#define AMIGAMOUSE_MINOR 4 FIXME OBSOLETE */
#define ATARIMOUSE_MINOR 5 /* unused */
#define SUN_MOUSE_MINOR 6 /* unused */
......
#define MISC_DYNAMIC_MINOR 255

        设置子设备号时要注意不要重复使用其他设备的子设备号。 可以从这些预定义的子设备号中选择一个, 也可以自定义。name 就是这个 misc 设备的名字, 当设备注册成功后, 会在/dev 目录下自动生成一个名为 name 的设备文件。 fops 就是这个 misc 设备的操作集合。
        当创建好 miscdevice 结构体后, 使用 misc_register 函数向系统中注册一个 misc 设备, 函数原型如下:

函数int misc_register(struct miscdevice * misc)
参数 misc之前创建好的 miscdevice 结构体
返回值成功返回 0, 失败返回负数。

         在设备驱动的卸载函数中, 使用 misc_deregister 函数来注销掉 misc 设备。 函数原型如下

函数int misc_deregister(struct miscdevice *misc)
参数 misc要注销的 miscdevice 结构体。
返回值

        在 miscdevice 结构体的第四行, 它指向了一个 file_operation 的结构体。 file_operations 文件操作集在定义在 include/linux/fs.h 下面, 如下图所示。

          file_operations 中的成员函数实际是由 drivers/char/misc.c 中 misc 驱动核心层的 misc_fops 成员函数间接调用的。 file_operations 结构体里面的结构体成员都对应一个调用。 简单介绍一下其中比较常用的函数:
llseek()函数用来修改一个文件的当前的读写位置, 并将新位置返回。
read()函数用来从设备中读取数据, 成功时返回读取到的字节数, 出错返回一个负值。
write()函数用来向设备发送数据, 成功时返回该函数写入的字节数。
poll()函数用于查询设备是否可以进行非阻塞读写。
unlock_ioctl()函数提供设备相关控制命令的实现。
mmap()函数将设备内存映射到进程的虚拟地址空间中。
open()函数用于打开设备文件。
release()函数用于关闭设备文件。
注册杂项设备有一个通用的思路和方法, 这里给大家总结为三个步骤:
填充 miscdevice 这个结构体
填充 file_operations 这个结构体
注册杂项设备并生生成设备节点。
 实验程序

添加头文件

/*注册杂项设备头文件*/
#include
/*注册设备节点的文件结构体*/
#include

填充 miscdevice 结构体

struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,.name = "hello_misc",.fops = &misc_fops,
};

上述代码第 2 行的 minor 为 MISC_DYNAMIC_MINOR, miscdevice 核心层会自动找一个空闲的次设备号,否则用 minor 指定的次设备号。 上述代码第 3 行 name 是设备的名称, 自定义为"hello_misc"
填充 file_operations 结构体

struct file_operations misc_fops={.owner = THIS_MODULE
};

        THIS_MODULE 宏是什么意思呢? 它在 include/linux/module.h 里的定义是
    #define THIS_MODULE (&__this_module)
        它是一个 struct module 变量, 代表当前模块, 可以通过 THIS_MODULE 宏来引用模块的 struct module结构, 比如使用 THIS_MODULE->state 可以获得当前模块的状态。 这个 owner 指针指向的就是你的模块。
注册杂项设备并生成设备节点
        在 misc_init()函数中填充 misc_register()函数注册杂项设备, 并判断杂项设备是否注册成功。

static int misc_init(void){int ret;ret &#61; misc_register(&misc_dev); //注册杂项设备if(ret<0) //判断杂项设备是否注册成功{printk("misc registe is error \n"); //打印杂项设备注册失败} printk("misc registe is succeed \n"); //打印杂项设备注册成功return 0;
}在 misc_exit&#xff08;&#xff09; 函数中填充 misc_deregister()函数注销杂项设备。static void misc_exit(void){misc_deregister(&misc_dev); //注销杂项设备printk("misc gooodbye! \n"); //打印杂项设备注销成功
}

完整的代码如下图所示&#xff1a;
 

/*
* &#64;Descripttion: 最简单的杂项设备驱动
* &#64;version:
* &#64;Author: topeet
*/
#include //初始化头文件
#include //最基本的文件&#xff0c; 支持动态添加和卸载模块。
#include /*注册杂项设备头文件*/
#include /*注册设备节点的文件结构体*/struct file_operations misc_fops&#61;
{ //文件操作集.owner &#61; THIS_MODULE
};
struct miscdevice misc_dev &#61;
{ //杂项设备结构体.minor &#61; MISC_DYNAMIC_MINOR, //动态申请的次设备号.name &#61; "hello_misc", //杂项设备名字是 hello_misc.fops &#61; &misc_fops, //文件操作集
};static int misc_init(void)
{ //在初始化函数中注册杂项设备int ret;ret &#61; misc_register(&misc_dev);if(ret<0){printk("misc registe is error \n");} printk("misc registe is succeed \n");return 0;
} static void misc_exit(void){ //在卸载函数中注销杂项设备misc_deregister(&misc_dev);printk(" misc gooodbye! \n");
} module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");

        现在最简单的杂项设备的驱动就写完了&#xff0c; 那么接下来我们可以把这个驱动编译一下&#xff0c; 然后放到开发板上面运行。 编译驱动&#xff0c; 可以将它编译进内核里面&#xff0c; 也可以将它编译成模块。
编译驱动程序
Makefile 为&#xff1a;

obj-m &#43;&#61; misc.o #先写生成的中间文件的名字是什么&#xff0c; -m 的意思是把我们的驱动编译成模块
KDIR:&#61;/home/topeet/driver/imx6ull/linux-imx-rel_imx_4.1.15_2.1.0_ga/
PWD?&#61;$(shell pwd) #获取当前目录的变量
all:make -C $(KDIR) M&#61;$(PWD) modules #make 会进入内核源码的路径&#xff0c; 然后把当前路径下的代码编译成
模块

驱动编译成功生成了 ko 文件&#xff0c; 如下图所示&#xff1a;

运行测试
 进入到共享目录&#xff0c; 加载驱动模块如图所示&#xff1a;
cd imx6ull/
ls
cd misc/
insmod misc.ko

驱动加载成功后&#xff0c; 输入以下命令&#xff0c; 查看注册的设备节点是否存在&#xff0c; 如下图所示&#xff0c; 设备节点存在。
ls /dev/h*

输入以下命令拆卸驱动模块,如下图所示&#xff1a;
rmmod misc
 

 


推荐阅读
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 掌握PHP框架开发与应用的核心知识点:构建高效PHP框架所需的技术与能力综述
    掌握PHP框架开发与应用的核心知识点对于构建高效PHP框架至关重要。本文综述了开发PHP框架所需的关键技术和能力,包括但不限于对PHP语言的深入理解、设计模式的应用、数据库操作、安全性措施以及性能优化等方面。对于初学者而言,熟悉主流框架如Laravel、Symfony等的实际应用场景,有助于更好地理解和掌握自定义框架开发的精髓。 ... [详细]
  • 如何在Java中高效构建WebService
    本文介绍了如何利用XFire框架在Java中高效构建WebService。XFire是一个轻量级、高性能的Java SOAP框架,能够简化WebService的开发流程。通过结合MyEclipse集成开发环境,开发者可以更便捷地进行项目配置和代码编写,从而提高开发效率。此外,文章还详细探讨了XFire的关键特性和最佳实践,为读者提供了实用的参考。 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • 在进行网络编程时,准确获取本地主机的IP地址是一项基本但重要的任务。Winsock作为20世纪90年代初由Microsoft与多家公司共同制定的Windows平台网络编程接口,为开发者提供了一套高效且易用的工具。通过Winsock,开发者可以轻松实现网络通信功能,并准确获取本地主机的IP地址,从而确保应用程序在网络环境中的稳定运行。此外,了解Winsock的工作原理及其API函数的使用方法,有助于提高开发效率和代码质量。 ... [详细]
  • Spring Boot 实战(一):基础的CRUD操作详解
    在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 在主从复制架构中,Bingo_MySQL 同步工具的应用与优化具有重要意义。为确保高效同步,建议使用相同或兼容的 MySQL 版本,并确保两台服务器位于同一局域网内,且网络连接畅通无阻。若无法 ping 通,请检查 IP 配置及防火墙设置,以保证网络连通性。此外,合理的配置参数和定期维护也是提升同步性能的关键因素。 ... [详细]
  • BZOJ1034 详细解析与算法优化
    本文深入解析了BZOJ1034问题,并提出了优化算法。通过借鉴广义田忌赛马的贪心策略,当己方当前最弱的马优于对方最弱的马时进行匹配;同样地,若己方当前最强的马优于对方最强的马,也进行匹配。此方法在保证胜率的同时,有效提升了算法效率。 ... [详细]
  • 本文详细探讨了C语言中`extern`关键字的简易编译方法,并深入解析了预编译、`static`和`extern`的综合应用。通过具体的代码示例,介绍了如何在不同的文件之间共享变量和函数声明,以及这些关键字在编译过程中的作用和影响。文章还讨论了预编译过程中宏定义的使用,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 深入解析Tomcat:开发者的实用指南
    深入解析Tomcat:开发者的实用指南 ... [详细]
  • MySQL性能优化与调参指南【数据库管理】
    本文详细探讨了MySQL数据库的性能优化与参数调整技巧,旨在帮助数据库管理员和开发人员提升系统的运行效率。内容涵盖索引优化、查询优化、配置参数调整等方面,结合实际案例进行深入分析,提供实用的操作建议。此外,还介绍了常见的性能监控工具和方法,助力读者全面掌握MySQL性能优化的核心技能。 ... [详细]
author-avatar
哥的微笑帅_655
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有