ARM 裸机与 Linux 驱动对比及 Linux 内核入门
目录
ARM裸机代码和驱动的区别
Linux系统组成
内核五大功能
设备驱动分类
内核类型
驱动模块
驱动模块示例
Makefile配置
命令
编码辅助工具
内核中的打印函数
printk 函数
修改打印级别
编辑
打印级别含义
驱动多文件编译
示例
模块传递参数
命令行传递参数
支持的数据类型
module_param 函数
MODULE_PARM_DESC 函数
示例
module_param_array 函数
字符设备驱动
Linux系统中一切皆文件
字符设备驱动步骤
字符设备驱动的注册
编辑
字符设备驱动的注销
以下是本人学习时的一些笔记,对初入门的驱动可能会有一些帮助,希望可以帮到大家~
ARM裸机代码和驱动的区别
共同点:
- 都能够操作硬件。
不同点:
- 裸机编程是直接用C语言给寄存器写值。
- 驱动编程遵循一定的框架和规范,通过往寄存器写值来控制硬件。
- 裸机代码独立编译和执行,而驱动依赖于内核进行编译和执行。
- 裸机程序一次只能执行一个任务,而驱动可以支持并发执行多个任务。
- 裸机程序只需一个
main
函数即可,而驱动需要遵循内核的框架和流程。
Linux系统组成
- 用户空间(0-3G):每个进程独占0-3G的虚拟地址空间。
- 内核空间(3-4G):所有进程共享3-4G的虚拟地址空间。
- 系统调用:应用程序通过系统调用(软中断SWI)与内核交互。
内核五大功能
- 进程管理:负责进程的创建、销毁和调度。
- 文件管理:通过文件系统(如ext2/ext3/ext4/YAFFS/JFFS等)来管理文件。
- 网络管理:通过网络协议栈(如OSI/TCP/IP)处理数据包的封装和拆解。
- 内存管理:负责用户空间和内核空间内存的分配和回收。
- 设备管理:管理设备驱动,如字符设备、块设备和网络设备。
设备驱动分类
- 字符设备驱动:如LED、鼠标、键盘、LCD、触摸屏等。
- 按照字节为单位访问,支持顺序访问。
- 创建设备文件,通过
open
,read
,write
,close
等操作访问。
- 块设备驱动:如摄像头、U盘、eMMC等。
- 按照块(通常是512字节)访问,支持顺序和随机访问。
- 创建设备文件,通过
open
,read
,write
,close
等操作访问。
- 网络设备驱动:如网卡。
- 按照网络数据包进行收发。
内核类型
- 宏内核:将主要功能集成在一个内核中。
- 优点:运行效率高。
- 缺点:任何一个部分出错都可能导致整个内核崩溃。
- 示例:Ubuntu, Android
- 微内核:只包含最基本的功能,其他功能通过服务的形式在用户空间实现。
- 优点:更高的稳定性和安全性。
- 缺点:相对较低的运行效率。
- 示例:HarmonyOS, QNX
驱动模块
- 三要素:入口、出口、许可证。
- 入口:资源的申请。
- 出口:资源的释放。
- 许可证:通常使用GPL许可。
(__init可以不指定,及可以不写,但是正常是写的)
驱动模块示例
#include <linux/init.h>
#include <linux/module.h>//__init将hello_init放到.init.text段中
static int __init hello_init(void) {// 初始化函数return 0;
}//__exit将hello_exit放到.exit.text段中
static void __exit hello_exit(void) {// 清理函数
}//告诉内核驱动的入口地址(函数名为函数首地址)
module_init(hello_init);//告诉内核驱动的出口地址
module_exit(hello_exit);//许可证
MODULE_LICENSE("GPL");
Makefile配置
KERNELDIR := /lib/modules/$(shell uname -r)/build/
PWD := $(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modulesclean:make -C $(KERNELDIR) M=$(PWD) cleanobj-m += hello.o
命令
- 安装驱动模块:
sudo insmod hello.ko
- 卸载驱动模块:
sudo rmmod hello
- 查看已加载的模块:
lsmod
- 查看内核消息:
dmesg
- 清空内核消息:
sudo dmesg -C
或sudo dmesg -c
- 持续查看内核消息:
sudo dmesg -w
编码辅助工具
- 创建索引文件:
ctags -R
- 在vi中跳转至标签:
ctrl + ]
和ctrl + t
Ubuntu内核所对应的内核路径
内核中的打印函数
printk 函数
-
函数原型:
printk(打印级别 "内容")
-
示例:
printk(KERN_ERR "Fail%d", a); printk(KERN_ERR "%s:%s:%d\n", __FILE__, __func__, __LINE__); printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
-
查看内核打印级别:
vi -t KERN_ERR
-
内核打印级别定义:
#define KERN_EMERG "<0>" /* system is unusable */ #define KERN_ALERT "<1>" /* action must be taken immediately */ #define KERN_CRIT "<2>" /* critical conditions */ #define KERN_ERR "<3>" /* error conditions */ #define KERN_WARNING "<4>" /* warning conditions */ #define KERN_NOTICE "<5>" /* normal but significant condition */ #define KERN_INFO "<6>" /* informational */ #define KERN_DEBUG "<7>" /* debug-level messages */
-
打印级别范围:
- 从
<0>
到<7>
,<0>
为最高级别,<7>
为最低级别。
- 从
修改打印级别
-
查看当前打印级别:
cat /proc/sys/kernel/printk
-
打印级别的含义:
- 第一个数字:终端的级别。
- 第二个数字:消息的默认级别。
- 第三个数字:终端的最大级别。
- 第四个数字:终端的最小级别。
-
修改系统默认的级别:
su root echo 4 3 1 7 > /proc/sys/kernel/printk
-
添加修改级别命令:
echo 4 3 1 7 > /proc/sys/kernel/printk
打印级别含义
- 终端的级别:只有当消息的级别大于或等于终端级别时,消息才会在终端上显示。
- 消息的默认级别:如果没有特别指定,消息将采用此级别。
- 终端的最大级别:终端可以显示的最高级别。
安装驱动和卸载驱动时,消息会打印。
驱动多文件编译
示例
-
文件列表:
hello.c
add.c
-
Makefile:
obj-m := demo.o demo-y += hello.o add.o
-
说明:
-y
作用:将hello.o
和add.o
文件合并到demo.o
中。- 最终生成:
demo.ko
文件。
模块传递参数
命令行传递参数
- 命令示例:
sudo insmod demo.ko hello world
支持的数据类型
- 标准类型:
byte
,short
,ushort
,int
,uint
,long
,ulong
charp
: 字符串指针bool
: 布尔值,接受0/1
,y/n
,Y/N
invbool
: 布尔值,接受0/1
,y/n
,Y/N
,但意义相反(N
表示真)
module_param 函数
- 函数原型:
module_param(name, type, perm);
- 参数:
name
: 变量的名字。type
: 变量的类型。perm
: 权限,如0664
,0775
。
MODULE_PARM_DESC 函数
- 函数原型:
MODULE_PARM_DESC(_parm, desc);
- 参数:
_parm
: 变量。desc
: 描述字段。
示例
-
命令行参数:
sudo insmod hello.ko a=20 b=30 c=65 p="hello_world"
-
注意事项:
- 传递字符时使用 ASCII 码值。
- 传递字符串时不能包含空格。
module_param_array 函数
- 函数原型:
module_param_array(name, type, nump, perm);
- 参数:
name
: 数组名。type
: 数组的类型。nump
: 参数的个数,变量的地址。perm
: 权限。
练习:
1.byte类型如何使用 (传递参数用ascii)
2.如何给一个指针传递一个字符串
- 命令行参数:
sudo insmod hello.ko a=121 b=10 c=65 p="hello" ww=1,2,3,4,5
传参成功~
字符设备驱动
Linux系统中一切皆文件
-
应用层:
fd = open("led驱动的文件", O_RDWR); read(fd); write(fd); close(fd);
-
内核层:
- 驱动文件:
led_driver.c
- 驱动函数:
driver_open(); driver_read(); driver_write(); driver_close();
- 驱动文件:
-
结构体定义:
struct file_operations {int (*open)(struct inode *, struct file *);ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);int (*release)(struct inode *, struct file *); ;
-
设备号:
- 32位无符号数字:
- 高12位:主设备号,用于区分设备类别。
- 低20位:次设备号,用于区分同一类别中的不同设备。
- 32位无符号数字:
-
硬件层:
- LED、UART、ADC、PWM 等设备。
字符设备驱动步骤
- 注册字符设备驱动 - 得到一个字符设备驱动的框架,并获得设备号。
- 确定操作的硬件设备 - 如 LED 灯(初始化灯)。
- 初始化灯 - 建立灯实际物理地址和虚拟地址之间的映射。
- 用户空间与内核空间数据交互 - 当用户使用时,驱动会被真正运行,涉及数据交互。
- 在应用层创建设备文件(设备节点)。
字符设备驱动的注册
-
函数原型:
int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops);
-
参数:
major
:主设备号。- 如果填写的值大于0,它认为这个就是主设备号。
- 如果填写的值为0,操作系统会分配一个主设备号。
name
:设备名称。fops
:操作方法结构体。
-
返回值:
major > 0
:成功返回0,失败返回错误码(负数)。major = 0
:成功返回分配的主设备号,失败返回错误码(负数)。
-
查看设备信息:
cat /proc/devices
字符设备驱动的注销
-
函数原型:
void unregister_chrdev(unsigned int major, const char *name);
-
参数:
major
:主设备号。name
:设备名称。
-
返回值:无。
就分享到这,希望可以帮到你吧~
相关文章:

ARM 裸机与 Linux 驱动对比及 Linux 内核入门
目录 ARM裸机代码和驱动的区别 Linux系统组成 内核五大功能 设备驱动分类 内核类型 驱动模块 驱动模块示例 Makefile配置 命令 编码辅助工具 内核中的打印函数 printk 函数 修改打印级别 编辑 打印级别含义 驱动多文件编译 示例 模块传递参数 命令行传递参数…...

0101DNS TCP fallback on UDP query timeout disabled-redission-中间件
文章目录 1.问题描述2.临时解决方案 结语 1.问题描述 Springcloud 项目,微服务模块使用redission,启动报错 DNS TCP fallback on UDP query timeout disabled. Upgrade Netty to 4.1.105 or higher.相关软件版本如下 软件版本描述springboot2.7.18spr…...

位运算
x1010 原码:000...1010 (一共32位) 反码:111...0101 (~x) 补码:111...0110 (反码1)(-x) 1、n 的二进制表示中第 k 位是几 #include<iost…...

MemFire Cloud是否真的可以取代后端
近年来,随着前端技术的迅速发展,前端工程师们越来越多地开始思考一个问题:“我还能不能不依赖后端?” 这种想法并非空穴来风,尤其是随着像MemFire Cloud这样的工具出现,它不仅能让开发者在没有后端的情况下…...

数据结构(邓俊辉)学习笔记】优先级队列 06——完全二叉堆:批量建堆
文章目录 1. 自上而下的上滤:算法2. 自上而下的上滤:效率3. 自下而上的下滤:算法4. 自下而上的下滤:实例5. 自下而上的下滤:效率 1. 自上而下的上滤:算法 在介绍过完全二叉堆标准的静态和动态操作接口之后…...

Java | Leetcode Java题解之第344题反转字符串
题目: 题解: class Solution {public void reverseString(char[] s) {int n s.length;for (int left 0, right n - 1; left < right; left, --right) {char tmp s[left];s[left] s[right];s[right] tmp;}} }...

定制开发AI智能名片O2O商城小程序:基于限量策略与个性化追求的营销创新
摘要:随着科技的飞速发展和消费者需求的日益多元化,传统商业模式正经历着前所未有的变革。在数字化转型的大潮中,定制开发AI智能名片O2O商城小程序作为一种新兴的商业模式,凭借其独特的个性化定制能力、高效的线上线下融合(O2O&am…...

Spring MVC Controller返回json日期格式配置失效的解决办法
如题,Spring MVC 4.3.0版本,配置jackson读写json。Controller层方法返回值对象包含java.util.Date类型的属性,并且在applicationContext.xml中配置了jackson的日期格式: <mvc:annotation-driven><mvc:message-converters…...

3.Default Constructor的构造操作
目录 1. 问题引入 2. 4种implicitly声明的default constructor 1. 问题引入 “default constructors......在需要的时候被编译产生出来”。关键词是“在需要的时候”,被谁需要,做什么事情?看看下面的代码,然后梳理下思路。 cl…...

CSS的:current伪类:精准定位当前活动元素
CSS(层叠样式表)是控制网页样式的核心语言。随着CSS4的提出,一系列新的选择器被引入,其中:current伪类便是这些新特性之一。:current伪类允许开发者选择当前处于活动状态的元素,这在创建动态和交互性网页时非常有用。本…...

搭建个人网站
一 个人搭建网站需要进行的操作 详细步骤: 1 网站目标:搭建在线查看法拍房拍卖价格的预测模型,输出预测结果 2 实际功能:在线爬取 阿里法拍网站的信息 3 根据实时模型建模预测法拍价格和成交概率 要搭建一个能够在线查看法拍房拍卖…...

机器学习课程学习周报八
机器学习课程学习周报八 文章目录 机器学习课程学习周报八摘要Abstract一、机器学习部分1.1 self-attention的计算量1.2 人类理解代替自注意力计算1.2.1 Local Attention/Truncated Attention1.2.2 Stride Attention1.2.3 Global Attention1.2.4 聚类Query和Key 1.3 自动选择自…...

福泰轴承股份有限公司进销存系统pf
TOC springboot413福泰轴承股份有限公司进销存系统pf 绪论 1.1 研究背景 现在大家正处于互联网加的时代,这个时代它就是一个信息内容无比丰富,信息处理与管理变得越加高效的网络化的时代,这个时代让大家的生活不仅变得更加地便利化&#…...

【k8s从节点报错】error: You must be logged in to the server (Unauthorized)
k8s主节点可以获取nodes节点信息,但是从节点无法获取,且报错“error: You must be logged in to the server (Unauthorized)” 排查思路: 当时证书过期了,只处理的主节点的证书过期,没有处理从节点的 kubeadm alpha …...

风清扬/基于Java语言的光伏监控系统+光伏发电预测+光伏项目+光伏运维+光伏储能项目
基于Java语言的光伏监控系统光伏发电预测光伏项目光伏运维光伏储能项目 介绍 基于Java语言的光伏监控系统光伏发电系统光伏软件系统光伏监控系统源码光伏发电系统源码 基于Java语言的光伏监控系统光伏发电预测光伏项目光伏运维光伏储能项目 安装教程 参与贡献 Fork 本仓库新…...

Datawhale X 魔搭 AI夏令营第四期 魔搭-AIGC方向全过程笔记
task1: 传送门 task2: 传送门 task3: 传送门 目录 Task1 赛题内容 可图Kolors-LoRA风格故事挑战赛 baseline要点讲解(请配合Datawhale速通教程食用) Step1 设置算例及比赛账号的报名和授权 Step2 进行赛事报名并创建PAI实例 Step3 执行baseline Step4…...

数组---怎么样定义和引用数组
一怎么定义数组 例 int a[10]; //定义了一个一维数组,数组名为a,此数组包含10个整型元素 所以我们了解到数组的基本定义为 类型符 数组名 [常量表达式] 定义数组可以包括常量和符号常量如 int [ 35 ];但是不能利用变量定义如 int n; …...

Nginx—Rewrite
目录 一、Nginx—Rewrite概述 1、常用的Nginx正则表达式 2、Rewrite功能 3、Rewrite跳转实现 4、Rewrite执行顺序和语法格式 二、location概述 1、location分类 2、location 常用的匹配规则 3、location 优先级 案例一: 案例二: 案例三&…...

《深入浅出WPF》读书笔记.5控件与布局(上)
《深入浅出WPF》读书笔记.5控件与布局(上) 背景 深入浅出WPF书籍学习笔记附代码。WPF中数据是核心是主动的,UI是数据的表达是被动的。 程序的本质是数据算法;控件的本质是数据行为; 5.控件与布局 一、6类控件派生关系 1.布局控件:可以容纳多个控件…...

二叉树的判断
二叉树的判断 判断一颗二叉树是不是搜索二叉树 (左边的比根小,右边的比根大) 中序遍历一下,如果是的话就一定是升序的 如何判断一颗二叉树是否是完全二叉树 1.遍历任意的节点时候,如果返回右孩子没有左孩子&#x…...

Hive3:常用的内置函数
1、查看函数列表 -- 查看所有可用函数 show functions; -- 查看count函数使用方式 describe function extended count;2、数学函数 -- round 取整,设置小数精度 select round(3.1415926); -- 取整(四舍五入) select round(3.1415926, 4); -- 设置小数精度4位(四…...

设计模式---构建者模式(Builder Pattern)
构建者模式(Builder Pattern) 是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离。它允许使用相同的构建过程创建不同的表示。该模式通常用于构建复杂对象,这些对象由多个部分组成或具有多个可选属性。 构建者模式的核…...

Pytorch中transform的应用
在PyTorch中,transforms模块主要用于对图像进行预处理和数据增强,以便于训练深度学习模型。这些转换操作可以包括裁剪、缩放、旋转、翻转等,以及对图像进行标准化处理。下面将详细介绍一些常用的transforms操作及其应用。 1. 常用的transfor…...

okular阅读软件简介
okular阅读软件官网:https://okular.kde.org/zh-cn/ Okular 是一款由 KDE 开发的跨平台文档阅读器,以其功能丰富、轻巧快速而著称。它支持多种文件格式,包括 PDF、EPub、DjVu、MD 文档,以及 JPEG、PNG、GIF、Tiff 和 WebP 图像&a…...

【书生大模型实战营(暑假场)闯关材料】基础岛:第1关 书生大模型全链路开源体系
【书生大模型实战营(暑假场)闯关材料】基础岛:第1关 书生大模型全链路开源体系 简介一、背景介绍1.1 背景介绍1.2 全链路开源开放体系的优势 二、全链路开源开放体系的主要特点2.1 模型组件的公开和共享2.2 数据集的公开和共享2.3 模型的互操…...

掌握抽象工厂模式:打造灵活且强大的跨平台产品族
抽象工厂模式是一种创建型设计模式,它的核心思想是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式通过使用抽象工厂来封装和隔离具体产品的创建过程,使得客户端可以通过工厂接口来创建一族产品,从…...

【Hadoop】建立圈内组件的宏观认识(大纲版)
Hadoop生态圈解析:各组件的主要功能及作用详解 Hadoop生态圈是由一系列开源组件组成的,这些组件共同构建了一个大规模分布式计算和存储平台。 01存储类型组件 HDFS Hadoop体系的核心组件之一,它是一个分布式文件系统,被设计用于存…...

NFS主从同步Rsync、sersync2
准备工作检查selinux 防火墙 #关闭 selinux sed -i s/^SELINUX.*/SELINUXdisabled/ /etc/selinux/config #关闭防火墙 systemctl stop firewalld;systemctl disable firewalld1.安装nfs相关包 # 所有节点安装nfs相关包 yum install nfs-utils -y systemctl enable nfs-utils …...

uniapp项目中,在原有数据中增加选中的状态,数据不改变
uniapp项目中,在原有数据中增加选中的状态,选中后打印的数据显示有变化,然而文本的数据并没有发生变化 看代码 export default {data() {return {thicate: [{ id: 1, text: "Item 1" },{ id: 2, text: "Item 2" },{ id…...

WPF自定义控件
控件模板 顾名思义就是在原有的控件上进行模版修改成自己需要的样式 把ProgressBar修改为一个水液面的进度条 <Window x:Class"XH.CustomLesson.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://s…...