字符设备驱动框架的编写

一. 简介

我们在学习裸机或者 STM32 的时候关于驱动的开发就是初始化相应的外设寄存器,在 Linux 驱动开发中,肯定也是要初始化相应的外设寄存器。
只是在 Linux 驱动开发中, 我们需要按照其规定的框架来编写驱动,所以说学 Linux 驱动开发重点是学习其驱动框架。

本文继上一篇文章的学习,前面几篇文章对字符设备驱动进行了简单的了解。文章地址如下:

字符设备驱动开发基础-CSDN博客

本文学习字符设备驱动的开发,主要学习字符设备驱动模块的加载与卸载。

二.  编写字符设备驱动框架

1.  Linux驱动的运行方式

Linux 驱动有两种运行方式,第一种就是将驱动编译进 Linux 内核中,这样当 Linux 内核启 动时就会自动运行驱动程序。
第二种就是将驱动编译成模块 (Linux 下模块扩展名为 .ko) ,在 Linux 内核启动以后使用 “ insmod ” 命令加载驱动模块。

选择驱动运行方式

在调试驱动时,一般都选择将其编译 为(.ko)模块,这样我们修改驱动以后,只需要编译一下驱动代码即可,不需要编译整个 Linux 代码。 而且在调试的时候只需要加载或者卸载驱动模块即可,不需要重启整个系统。总之,将驱动编 译为模块最大的好处就是方便开发,当驱动开发完成,确定没有问题以后就可以将驱动编译进 Linux 内核中。

2.   驱动的加载与卸载

模块有加载和卸载两种操作,我们在编写驱动时,需要注册这两种操作函数,模块的加载和 卸载注册函数如下:
module_init(xxx_init);   //注册模块加载函数
module_exit(xxx_exit);   //注册模块卸载函数
module_init() 函数用来向 Linux 内核注册一个模块加载函数,参数 xxx_init 就是需要注册的具体函数,当使用 “ insmod ” 命令加载驱动时, xxx_init() 这个函数就会被调用。
module_exit() 函数用来向 Linux 内核注册一个模块卸载函数,参数 xxx_exit 就是需要注册的具体函数,当使 用 “ rmmod ” 命令卸载具体驱动时, xxx_exit() 函数就会被调用。

3.  编写字符设备驱动框架

(1)  在 ubuntu系统下,创建一个存放驱动代码工程的目录,我这里在自己之前创建的正点原子文件目录下创建:

用 vscode软件打开 上面创建的工程目录 1_chrdevbase。通过 vscode在 目录 1_chrdevbase下创建一个 .c文件,命名为 chrdevbase.c,如下所示:

(2)  使用 vscode软件再打开 Linux内核源码,这里使用之前我更改的 NXP官方的 Linux内核源码。

Linux内核源码一般都会有使用到 驱动模块加载与卸载注册函数的。

在 Linux内核源码工程中,搜索 module_init() 函数与 module_eixt() 函数:

可以看到,Linux内核源码中,很多地方有调用到 module_init() 函数。当然也会调用到 module_exit()函数。

可以打开一个调用 module_init()函数的 .c文件,模仿 如何调用 module_init()函数。这里打开 aes_glue.c 文件,aes_glue.c文件中涉及 module_init()与 module_exit()函数的代码:

.......................................
static int __init aes_init(void)
{
	return crypto_register_alg(&aes_alg);
}

static void __exit aes_fini(void)
{
	crypto_unregister_alg(&aes_alg);
}

module_init(aes_init);
module_exit(aes_fini);
.......................................

模仿上面驱动模块的加载与卸载函数,编写 我的 chrdevbase.c 文件,再根据 上面 aes_glue.c中头文件添加相应的头文件,chrdevbase.c 文件的代码如下:

#include <linux/module.h>

/*
*  驱动模块入口函数
*/
static int __init chrdevbase_init(void)
{
	return 0;
}

/*
*  驱动模块出口函数
*/
static void __exit chrdevbase_exit(void)
{
	;
}

/*
* 驱动模块的入口与出口函数
*/
module_init(chrdevbase_init); /* 入口 */
module_exit(chrdevbase_exit); /* 出口 */

(3) 设置vscode软件中 1_chrdevbase工程的 头文件路径。具体设置 Linux内核源码路径。

不设置的话,vscode可能会提示一些错误,一些函数也找不到函数定义。

将正点原子提供的 Linux驱动例程中,01_chrdevbase工程代码中 .vscode文件及其下的文件都拷贝到 现在的 工程下。我这里没有安装 FTP客户端,所以,没办法拷贝文件夹。所以,可以在我1_chrdevbase工程下首先创建 .vscode目录,再在 .vscode目录下分别创建文件,将正点原子提供的 01_chrdevbase工程代码中 .vscode目录下文件的内容分别拷贝到相应文件。

.vscode目录下,创建如下两个文件:

编写驱动的时候注意事项:

(1) 编译驱动时需要用到 Linux内核源码!因此,需要解压缩 Linux内核源码。因为驱动代码中可能会调用到Linux内核源码中的一些函数。

同时,还需要编译linux内核源码,得到zImage和 .dtb设备树文件。需要使用编译后得到的zImage和 .dtb设备树文件来启动系统。

使用的Linux内核源码包:

这里使用正点原子第三期我编译的 Linux内核源码,也就是 在 NXP官方提供的 Linux内核源码更改后的 Linux内核源码包。

我这里的 Linux内核源码所在路径为:

/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga

更改 .vscode目录下 c_cpp_propertities.json文件下的 Linux源码路径:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/include", 
                "/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include", 
                "/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated/"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}

下一篇文章学习对工程进行编译,并加载与卸载字符驱动模块。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker介绍,Docker安装

docker镜像仓库官网 一、Docker的基本概念 1.Docker的三大核心组件 docker 镜像 --------docker images docker 仓库---------docker registeries docker 容器---------docker containers 2.Docker 镜像 Docker镜像是运行docker容器时的只读模板&#xff0c;每一个镜像由一…

设计模式——迭代器模式

引言 迭代器模式是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等&#xff09; 的情况下遍历集合中所有的元素。 问题 集合是编程中最常使用的数据类型之一。 尽管如此&#xff0c; 集合只是一组对象的容器而已。 大部分集合使用…

springboot221酒店管理系统

springboot221酒店管理系统 源码获取&#xff1a; https://docs.qq.com/doc/DUXdsVlhIdVlsemdX

CentOS7安装教程

1.准备工作 安装虚拟机软件 VMware Workstation 17 Player下载CentOS7 镜像 2. 安装VMware Workstation 17 Player 官网 下载链接 下载好了安装包&#xff0c;双击安装包&#xff0c;傻瓜式安装一直下一步&#xff0c;安装即可。 3. 安装CentOS7 官网 推荐下载地址&…

Vue 按键修饰符

常用按键修饰符&#xff1a;enter【回车】、delete【删除】、esc【退出】、space【空格】、tab【缩进】、up【上】、down【下】、left【左】、right【右】 。 系统按键修饰符&#xff1a;ctrl、alt、shift、meta【四个小方块】 。 鼠标修饰符&#xff1a;left【左键】、right…

计算机服务器中了mkp勒索病毒怎么办,mkp勒索病毒解密恢复

在计算机技术飞速发展的今天&#xff0c;越来越多的企业走向了数字化办公模式&#xff0c;极大地方便了企业的生产运营&#xff0c;为企业带来了更高的效率。但网络威胁无处不在&#xff0c;网络威胁手段随着计算机技术的不断发展也在不断增加。近期&#xff0c;云天数据恢复中…

【MySQL】存储过程/参数验证/函数

文章目录 存储过程是什么&#xff1f;创建存储过程&#xff1a;creat procedure…begin…end修改默认分隔符&#xff1a;dilimiter调用存储过程&#xff1a;call删除存储过程&#xff1a;drop procesure if exists练习 存储过程中添加参数&#xff1a;(形参 数据类型)示例练习 …

RocketMQ系统性学习-SpringCloud Alibaba集成RocketMQ以及批量发送消息、消息过滤实战

文章目录 批量发送消息消息过滤 批量发送消息 批量发送消息可以减少网络的 IO 开销&#xff0c;让多个消息通过 1 次网络开销就可以发送&#xff0c;提升数据发送的吞吐量 虽然批量发送消息可以减少网络 IO 开销&#xff0c;但是一次也不能发送太多消息 批量消息直接将多个消…

docker-harbor仓库

Docker 镜像 容器 仓库 仓库&#xff1a;保存镜像 私有&#xff1a;自定义用户的形式登录仓库&#xff0c;拉取或者上传镜像&#xff08;内部管理的用户&#xff09; Harbor&#xff1a;是VMware公司开发的&#xff0c;开源的企业级的docker register项目 帮助用户快速的搭建…

对DataFrame中每列的数值进行限值 指定最小值和最大值:超过最大值的数据,则改为最大值小于最小值的数据,则改为最小值 DataFrame.clip()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 对DataFrame中每列的数值进行限值 指定最小值和最大值&#xff1a; 超过最大值的数据&#xff0c;则改为最大值 小于最小值的数据&#xff0c;则改为最小值 DataFrame.clip() [太阳]选择题 请…

GoLang 学习 (入门)

go run 1.go 执行命令 go build 1.go 打包为exe 快速 并且无依赖 在开始项目 需要 生成 go.mod go mod init mod 终端执行 go: creating new go.mod: module mod go: to add module requirements and sums:go mod tidy go的基本目录结构 src ------gocode ------------项…

整合SpringSecurity

目录 前言 数据库设计 用户表 角色表 用户角色表 权限表 角色权限表 插入数据 表的实体类 用户表实体类 角色表实体类 权限表实体类 mapper层接口 UserMapper RoleMapper AuthorityMapper 封装登录信息 统一响应结果 上下文相关类 jwt令牌工具类 依赖导入…

Win11极速安装Tensorflow-gpu+CUDA+cudnn

文章目录 0.pip/conda换默认源1.Anacondapython虚拟环境2.安装CUDA以及cudnn测试tensorflow的GPU版本安装成功的办法参考文献 不要使用官网版本&#xff0c;直接使用conda版本&#xff0c;有对应的包&#xff0c;安装很方便 0.pip/conda换默认源 为了高效下载&#xff0c;建议…

nodejs微信小程序+python+PHP邮件过滤系统的设计与实现-计算机毕业设计推荐

邮件过滤系统综合网络空间开发设计要求。该系统主要设计并完成了管理过程中的用户登录、个人信息修改、邮件信息、垃圾箱、意见反馈、论坛等功能。该系统操作简便&#xff0c;界面设计简洁&#xff0c;不但可以基本满足本行业的日常管理工作&#xff0c; 目的是将邮件过滤通过网…

Flink系列之:自定义函数

Flink系列之&#xff1a;自定义函数 一、自定义函数二、概述三、开发指南四、函数类五、求值方法六、类型推导七、自动类型推导八、定制类型推导九、确定性十、内置函数的确定性十一、运行时集成十二、标量函数十三、表值函数十四、聚合函数十五、表值聚合函数 一、自定义函数 …

HttpRunner接口自动化测试框架

简介 HttpRunner是一款面向 HTTP(S) 协议的通用测试框架&#xff0c;只需编写维护一份 YAML/JSON 脚本&#xff0c;即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。 项目地址&#xff1a;GitHub - httprunner/httprunner: HttpRunner 是一个开源的 API/UI…

【MySQL表的增删改查】

目录&#xff1a; 前言表的增删改查Create(创建)1.插入插入测试插入否则更新 2.替换 Retrieve(查找)1.SELECT 列全列查找指定列查找查询字段为表达式字段重命名结果去重 2.WHERE条件英语不及格的同学及英语成绩&#xff08;<60&#xff09;语文成绩在 [80, 90] 分的同学及语…

RTOS队列的写入与读出

我们在stm32f103c8t6单片机上验证RTOS队列的写入与读出&#xff0c;利用stm32cube进行RTOS的配置。在选择TIM2当做RTOS的时钟&#xff0c;裸机的时钟源默认是 SysTick&#xff0c;但是开启 FreeRTOS 后&#xff0c;FreeRTOS会占用 SysTick &#xff08;用来生成1ms 定时&#x…

ChatGLM基于LangChain应用开发实践(一)

一、概述 在使用大模型&#xff08;LLM&#xff09;做应用开发时&#xff0c;LangChain是一个主流的开发框架&#xff0c;通过它来构建Agent&#xff0c;根据用户查询访问企业私有数据&#xff0c;调用自定义或者第三方工具库&#xff0c;然后再调用LLM&#xff0c;利用其推理…

qt-C++笔记之std::tostring()、.toStdString()、.toLocal8Bit().constData()的使用场景

qt-C笔记之std::tostring()、.toStdString()、.toLocal8Bit().constData()的使用场景 参考博文&#xff1a;C笔记之system()用于在Qt中执行系统命令的习惯 code review! 注&#xff1a;之所以记录该笔记&#xff0c;是因为在Qt中自己经常使用C语言的int system( const char …
最新文章