【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十九章 Linux MISC驱动

news2024/11/24 1:31:37

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT、4G模块、CAN、RS485等接口一应俱全。H264、VP8视频硬编码,H.264、H.265、VP8、VP9视频硬解码,并提供相关历程,支持8路PDM接口、5路SAI接口、2路Speaker。系统支持Android9.0(支持获取root限)Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9系统。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于任何通用工业和物联网应用、

【公众号】迅为电子

【粉丝群】258811263(加群获取驱动文档+例程)


第三部分 Linux驱动基础

十九Linux MISC驱动

本章导读

Linux MISC驱动是最简单的字符设备驱动,学习MISC驱动将会为学习字符设备驱动奠定基础。

39.1 章节讲解了misc设备驱动的基本概念及函数使用方法

39.2 章节讲解了编写最简单的杂项设备驱动,并将其编译为驱动模块,在iTOP-3399开发板上运行测试。

本章内容对应视频讲解链接(在线观看):

杂项设备驱动讲解  杂项设备驱动讲解_哔哩哔哩_bilibili

编写一个杂项设备驱动  https://www.bilibili.com/video/BV1Vy4y1B7ta?p=10

程序源码在网盘资料“iTOP-i.MX8MM开发板\02-i.MX8MM开发板网盘资料汇总(不含光盘内容)\嵌入式Linux开发指南(iTOP-i.MX8MM)手册配套资料\2.驱动程序例程\02-杂项设备驱动实验”路径下。

39.1 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结构体的定义在内核源码具体定义/home/topeet/linux/linux-imx/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 设备的设备号,定义在/home/topeet/linux/linux-imx/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,失败返回负数。

 

我们设置子设备号时要注意不要重复使用其他设备的子设备号。可以从这些预定义的子设备号中选择

一个,也可以自定义。

name 就是这个 misc 设备的名字,当设备注册成功后,会在/dev 目录下自动生成一个名为 name 的设备文件。fops 就是这个 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这个结构体
  • 注册杂项设备并生生成设备节点。

 

39.2 编写实验程序

通过39.1章节的学习,我们已经把杂项设备的基本概念搞懂了,在本实验中,使用 misc 设备驱动的方式来编写最简单的杂项设备的驱动。

39.2.1 编写驱动例程

首先我们回想一下注册杂项设备的三大流程,我们在Windows上面新建misc.c文件,并用sourceinsight打开。我们可以将上次编写的helloworld.c里面的代码拷贝到misc.c文件,并修改为如下图所示:

添加头文件

/*注册杂项设备头文件*/

#include <linux/miscdevice.h>

/*注册设备节点的文件结构体*/

#include <linux/fs.h>

填充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 = misc_register(&misc_dev);             //注册杂项设备
    if(ret<0)                                   //判断杂项设备是否注册成功
    {
        printk("misc registe is error \n");     //打印杂项设备注册失败
    }
    printk("misc registe is succeed \n");       //打印杂项设备注册成功
    return 0;
}
在misc_exit()函数中填充misc_deregister()函数注销杂项设备。
 static void misc_exit(void){
    misc_deregister(&misc_dev);                 //注销杂项设备
    printk("misc gooodbye! \n");                //打印杂项设备注销成功
}

 完整的代码如下图所示:

/*
 * @Descripttion: 最简单的杂项设备驱动
 * @version: 1.0
 * @Author: topeet
 */
#include <linux/init.h>              //初始化头文件
#include <linux/module.h>            //最基本的文件,支持动态添加和卸载模块。
#include <linux/miscdevice.h>        /*注册杂项设备头文件*/
#include <linux/fs.h>                /*注册设备节点的文件结构体*/
struct file_operations misc_fops = { //文件操作集
    .owner = THIS_MODULE};
struct miscdevice misc_dev = {
    //杂项设备结构体
    .minor = MISC_DYNAMIC_MINOR, //动态申请的次设备号
    .name = "hello_misc",        //杂项设备名字是hello_misc
    .fops = &misc_fops,          //文件操作集

};
static int misc_init(void)
{ //在初始化函数中注册杂项设备
    int ret;
    ret = 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");

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

39.2.2 编译驱动程序

这里我们以iTOP-i.MX8MM开发板为例,将杂项设备驱动编译成模块,请参考本手册第三十Linux内核模块。我们将misc.c文件拷贝到Ubuntu的/home/topeet/imx8m/02目录下。将上次编译helloworld的Makefile文件和build.sh脚本拷贝到misc.c同级目录下,修改Makefile为:

obj-m += misc.o
KDIR:=/home/topeet/linux/linux-imx
PWD?=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	make -C $(KDIR) M=$(PWD) clean

文件如下图所示:

驱动编译成功生成了ko文件,如下图所示:

39.2.3 运行测试

启动iTOP-iMX8MM开发板,我们通过nfs挂载共享文件目录,我们进入到共享目录,加载驱动模块如图所示:

insmod misc.ko

 

驱动加载成功后,输入以下命令,查看注册的设备节点是否存在,如下图所示,设备节点存在。

ls /dev/h*

 

我们输入以下命令拆卸驱动模块,如下图所示:

rmmod misc

 

那么,现在最简单的杂项设备已经完成了。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫实战:解决代理IP频繁中断的实操建议

当代理IP在爬虫中频繁掉线时&#xff0c;我们先要了解出现问题的可能原因&#xff0c;这不仅限于技术性因素&#xff0c;还涉及操作策略和环境因素。只有在找到具体原因后&#xff0c;才能针对问题类型从源头解决IP掉线问题。 一、问题原因&#xff1a; 1. 代理IP质量问题导致…

数据结构(Java):七大排序算法【详解】

目录 1、排序的概念 1.1 排序 1.2 排序的稳定性 1.3 内部排序&外部排序 1.4 各排序算法总结对比 2、 插入排序 2.1 &#x1f338;直接插入排序 2.2 &#x1f338;希尔排序 3、 选择排序 3.1 &#x1f338;直接选择排序 3.2 直接选择排序优化 3.3 &#x1f338;…

清华大学联合斯坦福大学提出混合注意力机制MoA,大模型解码速率提高6倍

随着大语言模型的规模不断扩大&#xff0c;如何在保持模型性能的同时提高其效率&#xff0c;成为了当前研究的热点问题。最近&#xff0c;清华大学联合斯坦福大学提出一种名为"注意力混合"(Mixture of Attention, MoA)的新方法&#xff0c;用于自动压缩大语言模型。 …

ES中的数据类型学习之ALIAS

Alias field type | Elasticsearch Guide [7.17] | Elastic 这里只针对data type的alias&#xff0c;暂时不说 index的alias。直接实战开始 PUT trips { "mappings": { "properties": { "distance": { "type": &…

开源安全态势感知平台Security Onion

简介 Security Onion是一款由安全防御人员为安全防御人员构建的免费开放平台。它包括网络可见性、主机可见性、入侵检测蜜罐、日志管理和案例管理等功能。详细信息可以查看官网Security Onion Solutions 在网络可见性方面&#xff0c;Security Onion提供了基于签名的检测&…

【系统架构设计 每日一问】二 MySql主从复制延迟可能是什么原因,怎么解决

主从复制的架构设计如下图所示&#xff1a; 同步原理 具体到数据库之间是通过binlog和复制线程操作的&#xff1a; Master的更新事件(update、insert、delete)会按照顺序写入bin-log中。当Slave连接到Master的后,Master机器会为Slave开启&#xff0c;binlog dump线程,该线程…

go关于string与[]byte再学深一点

目标&#xff1a;充分理解string与[]bytes零拷贝转换的实现 先回顾下string与[]byte的基本知识 1. string与[]byte的数据结构 reflect包中关于字符串的数据结构 // StringHeader is the runtime representation of a string.type StringHeader struct {Data uintptrLen int} …

浅谈断言之XML断言

浅谈断言之XML断言 XML断言是JMeter的一个组件&#xff0c;用于验证请求的响应数据是否符合XML结构。这对于测试返回XML格式数据的Web服务特别有用。 如何添加XML断言&#xff1f; 要在JMeter测试计划中添加XML断言&#xff0c;遵循以下步骤&#xff1a; 打开测试计划&…

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】 目录 JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现CPO-Transformer-LSTM多变量回归预测…

基于STM32F103的FreeRTOS系列(二)·多任务系统

基于STM32F103的FreeRTOS系列&#xff08;一&#xff09;单片机设计模式介绍裸机程序的设计模式-CSDN博客 目录 1. 多任务模式 2. 互斥操作 3. 同步操作 1. 多任务模式 对于裸机程序&#xff0c;无论使用哪种模式进行精心的设计&#xff0c;在最差的情况下都无法解决这个…

12. Hibernate 模板设计模式

1. 前言 本节课和大家一起使用模板设计模式重构 Hibernate 操作流程&#xff0c;通过本节课程内容&#xff0c;你将了解到&#xff1a; 如何运用模板设计模式重构 Hibernate 操作流程&#xff1b;持久化对象与序列化接口&#xff1b; 2. 模板设计模式 学习 Hibernate 的过程…

服务器上使用Docker部署sonarQube,并集成到Jenkins实现自动化。

目标是要在目标服务器上使用docker工具部署好sonar环境&#xff0c;然后再集成到Jenkins中实现自动化的代码审查工作。 Docker 首先Dokcer的源大部分现在都用不了&#xff0c;于是我上网查询&#xff0c;终于找到了一个可用的镜像。 编辑/etc/docker/daemon.json文件&#x…

71.PLC Settings for OPCSERVER(KEPWare)- SAP ME实施

目录 0.目的 1.三菱PLCMitsubishi Ethernet 1.1 型号FX-3U的配置 选择Operational settings 按下图设置通讯参数 选择Open settings 按下图设置通讯端口 选择Router ralay parameter 按下图设置网关 1.2型号Q Series 按下图设置IP、网关 按下图设置端口…

WebGoC题解(13) 狐猬编程:GoC L4 结业测试 第4题 找木柴

题目描述 小明今天找了n跟木柴&#xff0c;但是木柴太多了&#xff0c;小明只能拿走m根木柴&#xff0c;小明希望拿走的木柴都是剩下的木柴中最长的&#xff0c;小明还画出以下图形 例如 输入 5 3 10 20 30 40 50 小明要拿走30 40 50 这3根木柴 从大到小画出以下图形 矩形的宽…

AWS监控工具,监控性能指标

执行AWS监视是为了跟踪在AWS环境中主动运行的应用程序工作负载和资源&#xff0c;AWS监视器跟踪各种AWS云指标&#xff0c;以帮助提高在其上运行的应用程序的整体性能。 借助阈值突破警报系统&#xff0c;AWS应用程序监控在识别性能瓶颈来源方面起着至关重要的作用&#xff0c…

46 AP-AC实战图示

一 流程 一 无线上WEB页面 1 创建vlan 56 [AC-KongZhi]vlan 56 2 退出 [AC-KongZhi-vlan56]quit 3 进入vlan三层口 配置IP地址 [AC-KongZhi]interface Vlan-interface 56 [AC-KongZhi-Vlan-interface56]ip address 192.168.56.55 24 4 在AC控制器与Host主机的接口上能通关vl…

Adobe国际认证详解-动漫制作专业就业方向和前景

动漫制作专业的就业方向和前景随着创意产业的蓬勃发展而愈发广阔。这一专业涵盖了从角色设计、场景绘制到动画制作、特效合成等多个环节&#xff0c;是创意与技术相结合的典型代表。随着数字媒体和互联网的普及&#xff0c;动漫制作专业人才的需求正不断增长&#xff0c;为该专…

Chrome v8 pwn 前置

文章目录 参考用到啥再更新啥简介环境搭建depot_tools和ninjaturbolizer 调试turbolizer使用结构数组 ArrayArrayBufferDataViewWASMJSObject结构Hidden Class命名属性-快速属性Fast Properties命名属性-慢速属性Slow Properties 或 字典模式Dictionary Mode编号属性 (Elements…

redis的使用场景和持久化方式

redis的使用场景 热点数据的缓存。热点&#xff1a;频繁读取的数据。限时任务的操作&#xff1a;短信验证码。完成session共享的问题完成分布式锁。 redis的持久化方式 什么是持久化&#xff1a;把内存中的数据存储到磁盘的过程&#xff0c;同时也可以把磁盘中的数据加载到内存…

Ubuntu 24.04 LTS Noble安装 FileZilla Server

FileZilla Server 是一款使用图形用户界面快速创建 FTP 服务器的软件。它有助于测试需要 FTP 服务器功能的各种项目。虽然早期的 FileZilla FTP 服务器仅适用于 Windows 和 macOS&#xff0c;但现在我们也可以在 Linux&#xff08;例如 Ubuntu 24.04&#xff09;上安装 FileZil…