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、触摸屏等。
    • 按照字节为单位访问,支持顺序访问。
    • 创建设备文件,通过openreadwriteclose等操作访问。
  • 块设备驱动:如摄像头、U盘、eMMC等。
    • 按照块(通常是512字节)访问,支持顺序和随机访问。
    • 创建设备文件,通过openreadwriteclose等操作访问。
  • 网络设备驱动:如网卡。
    • 按照网络数据包进行收发。

内核类型

  • 宏内核:将主要功能集成在一个内核中。
    • 优点:运行效率高。
    • 缺点:任何一个部分出错都可能导致整个内核崩溃。
    • 示例: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
支持的数据类型
  • 标准类型
    • byteshortushortintuintlongulong
    • charp: 字符串指针
    • bool: 布尔值,接受 0/1y/nY/N
    • invbool: 布尔值,接受 0/1y/nY/N,但意义相反(N 表示真)

module_param 函数
  • 函数原型
    module_param(name, type, perm);
  • 参数
    • name: 变量的名字。
    • type: 变量的类型。
    • perm: 权限,如 06640775

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位:次设备号,用于区分同一类别中的不同设备。
  • 硬件层

    • LEDUARTADCPWM 等设备。
字符设备驱动步骤
  1. 注册字符设备驱动 - 得到一个字符设备驱动的框架,并获得设备号。
  2. 确定操作的硬件设备 - 如 LED 灯(初始化灯)。
  3. 初始化灯 - 建立灯实际物理地址和虚拟地址之间的映射。
  4. 用户空间与内核空间数据交互 - 当用户使用时,驱动会被真正运行,涉及数据交互。
  5. 在应用层创建设备文件(设备节点)。
字符设备驱动的注册
  • 函数原型

    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:设备名称。
  • 返回值:无。

就分享到这,希望可以帮到你吧~

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

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

相关文章

python-docx 实现 Word 办公自动化

前言&#xff1a;当我们需要批量生成一些合同文件或者简历等。如果手工处理对于我们来说不仅工作量巨大&#xff0c;而且难免会出现一些问题。这个时候运用python处理word实现自动生成文件可极大的提高工作效率。 python-docx是python的第三方插件&#xff0c;用来处理word文件…

Kubectl命令、初识pod、namespace

文章目录 一、Kubectl简介基础命令1.基本信息命令2.创建和更新资源命令3.删除资源命令4. 查看日志和调试命令5. 端口转发和复制文件命令6. 部署管理命令7. 伸缩命令8. 配置和上下文管理命令9.常用命令 二、Pod简介核心概念pod常见状态调度和初始化阶段容器创建和运行阶段异常状…

Qt网络通信——TCP和UDP

一、TCP通信 TCP通信必须先建立 TCP 连接&#xff0c;通信端分为客户端和服务器端。 Qt 为服务器端提供了 QTcpServer 类用于实现端口监听&#xff0c;QTcpSocket 类则用于服务器和客户端之间建立连接。大致流程如下图所示&#xff1a; 1. 服务器端建立 1.1 监听——listen() …

PPP简介

介绍PPP特性的定义和目的。 定义 PPP&#xff08;Point-to-Point Protocol&#xff09;协议是一种点到点链路层协议&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 目的 PPP协议是在串行线IP协议SLIP&#xff08;Serial Line Internet Protocol&#x…

代码随想录:动态规划6-10

62、不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径…

史上最全的软件工厂考试简答题教程

软件工程考试简答题 1. 有人认为软件开发时&#xff0c;一个错误发现得越晚&#xff0c;为改正它所付出的代价越大。提出你的观点并解释原因&#xff1f; &#xff08;1&#xff09;在软件开发的不同阶段进行修改付出的代价是很不相同的&#xff0c;在早期引入变动&#xff0c…

openai whisper使用

whisper使用 介绍 Whisper是一种通用的语音识别模型。它是在大量不同音频数据集上训练的&#xff0c;也是一个多任务模型&#xff0c;可以执行多语言语音识别、语音翻译和语言识别。 GitHub&#xff1a;https://github.com/openai/whisper 论文链接&#xff1a;https://arx…

注册Github账号详细过程

目录 一、准备工作 二、注册步骤 一、准备工作 在注册GitHub账号之前&#xff0c;请确保您已经准备好以下信息&#xff1a; 一个有效的电子邮箱地址&#xff1a;用于接收验证邮件和GitHub的后续通知。 用户名&#xff1a;确保该用户名在GitHub上是唯一的&#xff0c;且符合…

turtle画图知识

Turtle库是Python编程语言中的一个库&#xff0c;用于创建各种类型的图形&#xff0c;包括简单圆形、线条、路径和图片。它支持多种图形类型&#xff0c;并且可以绘制出各种复杂的形状。 以下是一些基本的使用方法&#xff1a; 1. 创建一个新的Turtle对象&#xff1a; pytho…

Leetcode JAVA刷刷站(53)最大子数组和

一、题目概述 二、思路方向 这个问题是一个经典的算法问题&#xff0c;称为“最大子序和”&#xff08;Maximum Subarray Problem&#xff09;。解决这个问题的一个高效方法是使用“Kadanes Algorithm”&#xff0c;它只需要遍历数组一次&#xff0c;就能在 O(n) 时间复杂度内…

CVPR2023《DNF: Decouple and Feedback Network for Seeing in the Dark》暗光图像增强论文阅读笔记

相关链接 论文链接 https://openaccess.thecvf.com/content/CVPR2023/papers/Jin_DNF_Decouple_and_Feedback_Network_for_Seeing_in_the_Dark_CVPR_2023_paper.pdf 代码链接 https://github.com/Srameo/DNF 摘要 RAW数据的独特属性在低光照图像增强方面展现出巨大潜力。…

C语言典型例题47

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题3.7 输入4个整数&#xff0c;要求按照从小到大的顺序输出 4个数之间进行比较&#xff0c;冒泡排序最最最详细过程&#xff0c;如果想更改为任意数之间相互比较&#xff0c;只需要修改两个地方&#xff08;数组大…

力扣面试经典算法150题:买卖股票的最佳时机 II

买卖股票的最佳时机 II 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a;买卖股票的最佳时机 II。 题目链接&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 问…

教程:postman的平替hoppscotch,又叫postwoman,hoppscotch的docker-compose安装过程

目录 1. 背景2. 前期准备2.1 准备docker-compose文件&#xff0c;两个版本&#xff0c;一个3合1&#xff0c;一个分开2.1.1 3合1版本&#xff08;推荐&#xff09;2.1.2 独立版本 2.2 准备安装nginx-proxy-manager&#xff08;可选&#xff09;2.2 准备.env文件2.2.1 默认ip的.…

Spring Boot OAuth2.0应用

本文展示Spring Boot中&#xff0c;新版本OAuth2.0的简单实现&#xff0c;版本信息&#xff1a; spring-boot 2.7.10 spring-security-oauth2-authorization-server 0.4.0 spring-security-oauth2-client 5.7.7 spring-boot-starter-oauth2-resource-server 2.7.10展示三个服务…

Android高版本抓包总结

方案1 CharlesVirtualXposedJustTrustMe 推荐使用三星手机此方案 VirtualXposed下载链接&#xff1a;https://github.com/android-hacker/VirtualXposed/releases JustTrustMe下载链接&#xff1a;https://github.com/Fuzion24/JustTrustMe/releases/ 下载完成后使用adb命令…

从易车“超级818冠军之夜” 看如何借势体育营销点燃汽车消费热潮

编辑 | 魏力 发布 | 大力财经 导语&#xff1a;这个8月&#xff0c;是属于奥运的8月。 巴黎奥运会虽圆满落幕&#xff0c;但属于奥运健儿们的热度还在持续。在这股奥运热潮的带动下&#xff0c;全民运动热情持续释放&#xff0c;同时也激发出巨大的消费潜力。 赛场外&#…

黄热病疫苗市场调研:预计到 2030 年全球市场规模将达到 1.8 亿美元

一、黄热病疫苗市场研究 &#xff08;一&#xff09;发展趋势 1. 市场规模增长&#xff1a;据调研团队报告所示&#xff0c;预计到 2030 年全球黄热病疫苗市场规模将达到 1.8 亿美元&#xff0c;年复合增长率为 3.0%。这表明市场在未来几年将保持稳定增长态势。增长的原因主要…

LSI-9361阵列卡笔记

背景 要将raid0更改为JBOD直通模式 注意的点是要先将raid模式调整为JBOD之后重启机器&#xff0c;即可 备注&#xff1a;转换过程中硬盘中的数据未丢失。 步骤贴图 refer https://zhiliao.h3c.com/questions/dispcont/123250 https://blog.csdn.net/GreapFruit_J/article/…

Android Activity启动流程(Android 13)

文章目录 Android Activity启动流程(Android 13)概述流程图前提流程分析Activity#startActivity()Activity#startActivityForResult()Instrumentation#execStartActivity()ActivityTaskManager#getService() ActivityTaskManagerService#startActivity()ActivityTaskManagerSer…