HelloWorld驱动编写和加载驱动实验

news2024/9/22 15:32:41

HelloWorld驱动编写和加载驱动实验

  • Helloworld驱动实验
    • 驱动编写
    • 驱动的基本框架
  • 内核模块实验
    • 设置交叉编译器
      • 找到RK3568平台交叉编译器:
      • 解压交叉编译器:
      • 设置全局的交叉编译器环境
        • 验证交叉编译器环境
    • 编写Makefile
    • 编译模块
    • 模块的加载与卸载
    • 查看模块信息

Helloworld驱动实验

在学习 C 语言或者其他语言的时候,我们通常是打印一句“helloworld”来开启编程世界
的大门。学习驱动程序编程亦可以如此,使用 helloworld 作为我们的第一个驱动程序。
接下来开始编写第一个驱动程序—helloworld。

驱动编写

编写一个最简单的驱动——helloworld 驱动。helloworld.c 如下

#include <linux/module.h>   //模块加载函数和卸载函数需要的头文件
#include <linux/kernel.h> 
static int __init helloworld_init(void)       //驱动的入口函数
{
	printk(KERN_EMERG "helloworld_init\r\n"); //注意:内核打印用的是printk,而不是printf
	return 0;
}
static void __exit helloworld_exit(void)      // 驱动的入口函数
{
	printk(KERN_EMERG "helloworld_exit\r\n");
}

module_init(helloworld_init);           // 注册入口函数
module_exit(helloworld_exit);           // 注册出口函数
MODULE_LICENSE("GPL v2");               // 同意GPL开源协议
MODULE_AUTHOR("topeet");                //作者信息

驱动的基本框架

Linux 驱动的基本框架主要由模块加载函数,模块卸载函数,模块许可证声明,模块参数,
模块导出符号,模块作者信息等几部分组成,其中模块参数,模块导出符号,模块作者信息是
可选的部分,也就是可要可不要。剩余部分是必须有的。我们来看一下这几个部分的作用:
1、 模块加载函数
当使用加载驱动模块时,内核会执行模块加载函数,完成模块加载函数中的初始化工作。

2 、模块卸载函数
当卸载某模块时,内核会执行模块卸载函数,完成模块卸载函数中的退出工作。

3、 模块许可证声明
许可证声明描述了内核模块的许可权限,如果不声明模块许可,模块在加载的时候,会收
到“内核被污染(kernel tainted)”的警告。可接受的内核模块声明许可包括“GPL”“GPL v2”。

4 、模块参数(可选择)
模块参数是模块被加载的时候可以传递给它的值。

5 、模块导出符号(可选择)
内核模块可以导出的符号,如果导出,其他模块可以使用本模块中的变量或函数。

6 、模块作者信息等说明(可选择)

helloworld 驱动我们可以看作是驱动代码的模板。任何一个驱动代码都用它作为基础来编写实现

内核模块实验

设置交叉编译器

我们用的是RK3568平台,测试实验,那么用的RK平台配套的交叉编译器。用RK3568平台的交叉编译器放到 /usr/local 并解压,如下

找到RK3568平台交叉编译器:

gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.gz 放到对应的目录 /usr/local 下

解压交叉编译器:

解压交叉编译编译器压缩包,解压完毕会生成
“gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu.tar.gz”文件夹,这是实验需要的交叉编译工具
在这里插入图片描述

设置全局的交叉编译器环境

在ubuntu 终端输入“sudo vi /etc/profile”命令,在文件最后输入以下命令修改环境变量。
export PATH=$PATH:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin

export PATH=$PATH:/usr/local/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin

在这里插入图片描述

验证交叉编译器环境

设置全局交叉编译器环境后,保存,重启,在终端输入命令验证。验证命令:

aarch64-linux-gnu-gcc -v

如果返回如下结果,表示交叉编译器全局环境配置成功
在这里插入图片描述

编写Makefile

驱动helloworld.c 文件已经写好了,但是形成驱动文件,还需要配置一个Makefile 文件,再进行编译得到驱动文件,驱动加载才能让驱动跑起来。
下面开始介绍Makefile相关内容。

编译驱动程序还需要使用 Makefile 文件。我们为 helloworld.c 编写一个简单的 Makefile,
Makefile 文件和源文件 helloworld.c 位于同一级目录,标准模板如下:

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu- obj-m += helloworld.o #helloworld.c 对应.o 文件的名称。名称要保持一致。
KDIR :=/home/topeet/Linux/linux_sdk/kernel #内核源码所在虚拟机 ubuntu 的实际路径
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules #make 操作
clean:
make -C $(KDIR) M=$(PWD) clean #make clean 操作

实际配置,如下可借鉴:
在这里插入图片描述

代码解释如下:

1 行设置 ARCH 变量为 arm64
第 2 行设置交叉编译器前缀为 aarch64-linux-gnu-3 行 obj-m += <文件>:将指定的文件(需要是以.o 结尾)设为编译时以模块形式编译
第 4 行是设备树内核的源码路径,请大家根据实际内核路径进行修改。
第 5 行是获取当前目录的变量
第 7 行是编译 make 操作,会进入内核源码的路径,然后把当前路径下的代码编译成模块。
第 9 行是清除编译文件

注意两个配置参数:
交叉工具器路径配置:CROSS_COMPILE
KDIR :内核路径

编译模块

有了 Makefile 以后,输入“make”命令就可以编译 helloworld 驱动模块,然后执行make 进行编译,如下:
在这里插入图片描述
天坑: 不同的ubuntu或者不同的用户,要求和权限不一致,会导致各种permission问题,导致编译失败,可以自行解决。这里直接用root 权限执行make 命令,结果如下:


root@wfc-X99:/home/wfc/wfc/Linux/01_helloworld# ls -l
total 344
-rwxrwxrwx 1 nobody nogroup    468 Aug  6 23:56 Makefile
-rw-r--r-- 1 root   root         0 Aug  8 01:06 Module.symvers
-rwxrwxrwx 1 nobody nogroup    375 Aug  2 01:19 helloworld.c
-rw-r--r-- 1 root   root    163088 Aug  8 01:06 helloworld.ko
-rw-r--r-- 1 root   root       593 Aug  8 01:06 helloworld.mod.c
-rw-r--r-- 1 root   root     81992 Aug  8 01:06 helloworld.mod.o
-rw-r--r-- 1 root   root     84240 Aug  8 01:06 helloworld.o
-rw-r--r-- 1 root   root        55 Aug  8 01:06 modules.order

编译完生成 helloworld.ko 目标文件就是我们需要的内核模块。内核模块是以 ko 为后缀名

输入“make clean”命令清除编译文件,会回到.c 和 Makefile 两个文件的原始状态,清除所有的生成文件,如下:
在这里插入图片描述

模块的加载与卸载

有了内核模块以后,我们要如何使用呢?编译驱动有俩种方式,那 Linux 驱动的运行方式
也肯定有俩种。一种就是将驱动编译进内核,这样 Linux 系统启动后会自动运行程序。第二种
就是将驱动编译成模块,在 Linux 系统启动以后使用“insmod”命令加载驱动模块。
我们已经有了 编 译 了 驱 动 模 块 helloworld.ko, 在 RK3568 开 发 板 上 通 过 “ insmod
helloworld.ko”命令可以加载驱动,在加载驱动模块的时候会执行驱动入口的函数,也就是
helloworld 程 序 中 的 helloworld_init 函 数 , 所 以 可 以 看 到 打 印 出 来 的 字 符 串 信 息
“helloworld_init”。

重点:
这里涉及到开发环境,比如RK3568的开发板,开发板只是一个硬件环境,在这个硬件环境上面需要跑一个系统来支持驱动的加载。我们前面写Makefile 文件时候,已经了解了配置的交叉编译器、内核源码位置。那么这个环境其实就是交叉编译器编译出来的驱动能够运行的环境平台,且用了内核源码编译的内核。
环境的准备:
1、我们用RK3568开发版,用Ubuntu电脑编译一个Buildroot 系统跑上去,比如机器开机如下:这只是一个跑驱动的环境而已,也可以开发板上跑ubuntu系统,Buildroot 比较简单,方便测试而已。
2、有了开发版环境,如何把.ko 驱动模块放到开发版里面呢? 连接usb 后,直接adb push 到根目录,即可。 在adb 环境下或者串口连接环境下执行命令,查看结果。
在这里插入图片描述
如果要卸载 helloworld 内核模块,可以通过“rmmod helloworld”命令来卸载驱动模块,
同理在卸载驱动模块的时候会执行驱动出口的函数,所以可以看到驱动出口函数打印出来的字
符串信息“helloworld_exit”,

加载驱动模块也可以使用 modprobe 命令,它比 insmod 命令更强大,modprobe 命令在加
载驱动模块的时候,会同时加载该模块依赖的其他模块。比如 helloworld.ko 依赖 before.ko,
使用 insmod 加载的时候,就必须先加载 before.ko,然后在加载 helloworld.ko 才可以加载成功
从。但是使用 modprobe 加载的时候,他会自动分析模块的依赖关系,然后将所有的依赖的模
块都加载到内核当中。比较“聪明”。
同样,在卸载驱动模块的时候,如果模块存在依赖关系,如果使用 insmod 命令,需要手
动卸载依赖的内核模块,但是使用 modprobe 命令可以自动卸载驱动模块所依赖的其他模块。
所以,如果驱动模块是以“modprobe helloworld.ko”命令加载的,卸载的时候使用“modprobe
-r helloworld.ko”命令卸载。
但是使用 modprobe 卸载存在一个问题,如果所依赖的模块被其他模块所使用,比如刚才
例子中的 before.ko 还被其他的模块使用,这时候就不能使用 modprobe 卸载。所以还是推荐
使用 rmmod 命令来卸载。

查看模块信息

在驱动模块加载之后,使用“modinfo helloworld.ko”命令可以获得模块的信息,包括模块
作者,模块说明,模块支持的参数等等。
lsmod 命令可以列出已经载入 Linux 内核模块,在 helloworld 驱动加载之后,查看内核中
加载的模块,

[root@topeet:/]# insmod helloworld.ko
[root@topeet:/]# lsmod
Module                  Size  Used by    Tainted: G
helloworld             16384  0
rtk_btusb              57344  0
8723du               1560576  0
bcmdhd               1048576  0
[root@topeet:/]#

参考文件
helloworld驱动源码文件
参考Helloworld驱动和驱动加载实验视频教程
编译手册参考:BuildRoot系统编译
驱动开发指南文档

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

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

相关文章

WT2605C蓝牙语音芯片赋能对讲机新体验:无屏操控、音频解码与蓝牙音箱三合一

一、产品概况 对讲机市场是一个技术成熟且具有广泛应用前景的市场。对讲机作为无线通信设备的一种&#xff0c;在许多不同的领域和业务中发挥着重要作用。从技术发展角度来看&#xff0c;对讲机经历了从模拟到数字的转型&#xff0c;以及从简单通信工具向多功能设备的演进。当…

LVS实验——部署DR模式集群

目录 一、实验环境 二、配置 1、LVS 2、router 3、client 4、RS 三、配置策略 四、测试 1.Director服务器采用双IP桥接网络&#xff0c;一个是VPP&#xff0c;一个DIP 2.Web服务器采用和DIP相同的网段和Director连接 3.每个Web服务器配置VIP 4.每个web服务器可以出外网…

【Python机器学习】回归——缩减系数来“理解”数据

如果数据特征比样本点还多&#xff0c;是不可以使用线性回归的&#xff0c;因为在计算的时候会出错。 如果特征比样本点还多&#xff08;n>m&#xff09;&#xff0c;也就是说输入数据的矩阵x不是满秩矩阵。非满秩矩阵在求逆时会出问题。 为了解决上述问题&#xff0c;可以…

贪心算法的初涉(双指针 + “过山车思想”)

“过山车”思想 首先我们用一道力扣的题目&#xff0c;来简单了解一下“过山车思想” 3228. 将 1 移动到末尾的最大操作次数 - 力扣&#xff08;LeetCode&#xff09; 给你一个 二进制字符串 s。 你可以对这个字符串执行 任意次 下述操作&#xff1a; 选择字符串中的任一…

京东京造的C2M供应链模式

京东自有品牌业务于2018年1月正式上线&#xff0c;在京东发展已久&#xff0c;依托京东供应链优势&#xff0c;已搭建出京东京造、惠寻、佳佰等多品牌矩阵。 京东给零售企业释放出了一个讯号&#xff1a;C2M崛起&#xff0c;消费者的需求开始走向多元化和个性化&#xff01; …

徐州市委书记宋乐伟一行莅临非凸科技徐州分公司调研

7月23日&#xff0c;徐州市委书记宋乐伟一行莅临非凸科技徐州分公司调研&#xff0c;详细了解非凸科技数智交易产品的生态体系以及AI算力赋能的实践成果&#xff0c;并就相关工作进行了现场指导与交流。 非凸科技徐州分公司位于淮海路经济区金融服务中心云盛大厦&#xff0c;致…

基于JSP、java、Tomcat三者的项目实战--校园交易平台系统--(实习,答辩皆可用到)--万字爆更

技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 全部文件展示 网页实现功能截图 主页 注册 登录 购物车主页 修改功能 修改成功 添加商品功能 添加成功 添加进入购物车功能 支付功能 支付过的历史清单账单…

Comsol 声固耦合条件下超长水管路声传递损失

声固耦合条件指的是声波在固体和液体之间传递时&#xff0c;两者之间存在接触或耦合的情况。在水管路中&#xff0c;声固耦合条件下的声传递损失可以通过以下几个因素来影响和计算&#xff1a; 1. 声波的反射和透射&#xff1a;当声波从一个介质传递到另一个介质时&#xff0c…

服务器 Linux 的网络信息

博主上回大致讲解了文件系统&#xff0c;今天来说说 Linux 的网络信息&#xff0c;还是比较重要的~ 主机名称 临时修改 hostname node01 永久修改 vi /etc/hostname DNS解析 域名解析服务可以将域名转换为IP地址DNS域名劫持 window --> C:\Windows\System32\drivers…

Java 2.2 - Java 集合

Java 集合&#xff0c;也叫做容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection 接口&#xff0c;主要用于存放单一元素&#xff1b;另一个是 Map 接口&#xff0c;主要用于存放键值对。对于 Collection 接口&#xff0c;其下又有三个主要的子接口&#…

七大云安全威胁及其应对方法

关注公众号网络研究观获取更多内容。 对于任何依赖云来容纳快速增长的服务的企业来说&#xff0c;确保安全都是重中之重。然而&#xff0c;正如大多数云采用者很快意识到的那样&#xff0c;迁移到动态云环境需要新的和更新的安全措施&#xff0c;以确保数据和其他关键资产在整…

凯特王妃与戴安娜王妃:有跨越时空的优雅共鸣!

显而易见的是都是王妃,而王妃不仅是称谓也是一个头衔,她们同时要承担这个头衔应尽的职责! 在皇室世界里,总有一些名字,如同璀璨星辰,即便时光流转,依旧熠熠生辉。现在让我们揭开一段不为人知的幕后故事——凯特王妃与已故的戴安娜王妃之间,那些超越时代、共通的优雅与情…

前端模块化-手写mini-vite

前言 本文总结了一些关于 Vite 的工作原理&#xff0c;以及一些实现细节。 本节对应的 demo 可以在这里找到。 什么是 Vite Vite 是一个基于浏览器原生 ES imports 的开发服务器。利用浏览器去解析 imports&#xff0c;在服务器端按需编译返回&#xff0c;完全跳过了打包这个…

PyTorch深度学习实战(5)—— Tensor的命名张量和基本结构

1. 命名张量 命名张量&#xff08;Named Tensors&#xff09;允许用户将显式名称与Tensor的维度关联起来&#xff0c;便于对Tensor进行其他操作。笔者推荐使用维度的名称进行维度操作&#xff0c;这样可以避免重复计算Tensor每个维度的位置。支持命名张量的工厂函数&#xff08…

怎么删除iPhone重复照片:解放你的存储空间

在数字化时代&#xff0c;iPhone已成为我们记录生活点滴的重要工具。从家庭聚会的快乐时光到户外冒险的壮观景象&#xff0c;我们依靠iPhone捕捉无数珍贵瞬间。然而&#xff0c;这种便利性带来的一个副作用是&#xff0c;相册很快就会充满重复的照片&#xff0c;不仅占用了宝贵…

【IC设计】时序分析面试题总结(亚稳态、建立/保持裕量计算、最高时钟频率计算、时序违例解决办法)

文章目录 基本概念亚稳态建立时间和保持时间 常见问题1.为什么触发器要满足建立时间和保持时间&#xff1f;2.建立时间裕量和保持时间裕量的计算&#xff1f;3.最高时钟频率的计算&#xff1f;流水线思想&#xff1f;4.时序违例的解决办法&#xff1f; 基本概念 亚稳态 亚稳态…

简单的 CompletableFuture学习笔记

简单的 CompletableFuture学习笔记 这里记录一下自己学习的内容&#xff0c;简单记录一下方便后续学习&#xff0c;内容部分参考 CompletableFuture学习博客 1. CompletableFuture简介 在api接口调用时间过长&#xff0c;调用过多外围接口时&#xff0c;为了提升性能&#x…

Self-study Python Fish-C Note14 P50to51

函数 (part 4) 本节主要讲函数 递归 递归 (recursion) 递归就是函数调用自身的过程 示例1&#xff1a; def fun1(i):if i > 0: print(something)i-1fun1(i) fun1(5) # 这样就会打印五遍 somethingsomething something something something something要让递归正常工作&am…

IDEA2024.2重磅发布,更新完有4G!

JetBrains 今天宣布了其 IDE 家族版本之 2024.2 更新&#xff0c;其亮点是新 UI 现在已是默认设置&#xff0c;并且对 AI Assistant &#xff08;AI助手&#xff09;进行了几项改进。 安装密道 新 UI 的设计更加简约&#xff0c;可以根据需要以视觉方式扩展复杂功能。值得开发…

Arduino学习笔记2——初步认识Arduino程序

Arduino使用的编程语言是C。 一、注释文字 我们可以在程序中插入注释文字来提示开发者代码的作用。在Arduino中&#xff0c;单行注释用的是两个斜杠&#xff0c;多行注释用的是对称的斜杠加星号&#xff1a; 二、函数 和C语言相同&#xff0c;可以看到在打开IDE自动打开的默…