当前位置: 首页 > news >正文

驱动:驱动相关概念,内核模块编程,内核消息打印printk函数的使用

一、驱动相关概念

1.操作系统的功能

                向下管理硬件,向上提供接口

                操作系统向上提供的接口类型:

                内存管理:内存申请(malloc) 内存释放(free)等

                文件管理: 通过文件系统格式对文件ext2、ext3、 ext4格式进行管理

                进程管理: 进程的创建/调度/消亡

                网络管理: 通过网络栈协议,完成数据的收发

                 设备管理: 字符设备、块设备、网卡设备

 2.驱动的概念

                  2.1.定义

                       驱动是能够让硬件实现某个特定功能的软件代码,根据驱动代码是否使用了系统内核提供的接口,将驱动分为裸机驱动和系统驱动

                  2.2.裸机驱动和系统驱动

                         裸机驱动:不基于操作系统提供的接口完成驱动的编写,这种驱动比较简单,由开发者独立即可编写完成,但是实现的功能比较单一

                        系统驱动(操作系统设备驱动):编写驱动时调用系统内核提供的接口,驱动程序会被加载到内核空间。系统驱动开发者无法独立完成,需要操作系统内核的辅助,但是基于系统驱动完成的硬件控制工作会更加完善和复杂。

3.系统驱动(操作系统设备驱动)在操作系统中的层次

        设备驱动会被加载到系统内核空间,设备驱动主要完成对硬件功能的实现,相当于拓展了系统内核设备管理的功能

4.设备驱动的类型

       设备驱动的类型时根据设备类型的不同进行划分的,一般将设备分为字符设备、块设备、和网卡设备 三类:

                字符设备:以字节流的形式进行顺序访问的设备叫做字符设备。 90%的设备为字符设备,鼠标、键盘、摄像头...

                块设备:以块为单位进行随机访问的设备叫做块设备。块设备一般是一些磁盘设备

                网卡设备:用于进行网络数据传输的设备。网卡设备没有网卡设备文件,想要读取网卡设备的数据,需要基于socket套接字实现

二、内核模块编程

1.内核模块编程的意义

           驱动属于内核的一部分,驱动资源要加载到内核中,所以要按照内核模块的编程去编写框架

 2.内核模块的三要素

           入口:主要进行资源的申请工作,安装内核模块时执行

           出口:主要进行资源的释放工作,卸载内核模块时执行

           许可证:声明当前内核模块遵循GPL协议

 3.内核模块编写实例及代码解释

#inckude <linux/init.h>
#include <linux/module.h>//入口函数:安装内核模块时执行
static int __init mycdev_init(void)
{//static: 修饰当前函数只可在本文件使用//int:函数返回值类型,如果函数规定了返回值但是没有加返回值,编译会报错//mycdev_init:函数名,可以自己命名//void:表示函数无参数,void不可以省略//__init:告诉编译器当前函数保存在.init.text段  #define __init    sectoin(".init.text")//linux内核中有自己的链接脚本文件 vmlinux.lds,这个链接脚本文件规定了不同的内容存放在内存中的哪个位置return 0;
}//出口函数:卸载内核模块时执行
static void __exit mycdev_exit(void)
{//__exit:告诉编译器当前函数保存在.exit.text段  #define __exit    section(".exit.text")
}//声明入口函数
module_init(mycdev_init);
//声明出口函数
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

4.内核模块的编译

        编译内核镜像:make uImage

        编译设备树:make dtbs

        模块化编译:make modules

        内核模块编译有两种方式:内部编译和外部编译

        4.1内部编译

                内部编译又称为静态编译,需要依赖于内核的源码树:

                        ① 编写内核模块

                        ② 将内核模块文件移动到内核指定路径下

                        ③ 在内核指定路径下的Makefile文件中添加编译文件

                        ④ 修改Kconfig文件,添加当前内核模块文件的菜单选项(选配项)

                        ⑤  在源码顶层目录下make menuconfig将当前文件的选配项选配为M,保存退出,此时.config被修改

                        ⑥ make modules  进行模块化编译

         4.2.外部编译

                外部编译又称为动态编译,可以在内核路径外单独编译当前模块文件,外部编译需要我们自己手写Makefile

        通用版本的Makefile

modname ?= demo  #内核模块名称,询问赋值,若无对应的外部变量,则为demo,有则为外部变量
arch ?= arm  #架构,询问赋值,若无对应的外部变量,则为arm,有则为外部变量
ifed ($(arch),arm)    #通过命令行是否有对应的外部变量来判断采用什么架构进行编译#KERNRLDIR保存开发板内核源码路径KERNRLDIR := /home/ubuntu/linux.5.10.61/
else#KERNRLDIR保存ubuntu内核源码路径KERNRIDIR :=/lib/kernel/$(shell uname -r)/bulid   #uname -r命令是查找当前操作系统使用的内核版本
endif#PWD保存当前内核模块的路径
PWD := $(shell pwd)all:#make modules是模块化编译的命令#-C $(KERNELDIR) 表示执行make前到$(KERNELDIR)所保存路径下,读取该目录下的Makefile文件执行make编译#M=$(PWD) 指定模块化编译的路径,进行模块化编译的路径是PWD保存的路径make -C $(KERNELDIR) M=$(PWD) modules
clean:#编译删除make -C $(KERNELDIR) m=$(PWD) clean#将obj-m保存的文件单独链接生成内核模块
obj-m := $(modname).o    #此处写.o不写.c,虽然当前目录下没有.o文件,但是Makefile有自动推导功            能,会自动寻找对应.c

5.内核模板操作相关命令

        安装内核模块命令 insmod *.ko

        卸载内核模块命令 rmmod *.ko (后缀名.ko可省略)

        查看内核已经安装的内核模块 lsmod

        查看某个内核模块的信息 modinfo *.ko

三、内核消息打印函数printk函数的使用

1.printk函数的使用格式

        printk("格式控制符",输出列表)

                这种格式消息按照默认输出级别进行输出

        或

        printk(消息级别 "格式控制符",输出列表)

2.printk函数消息队列打印级别

        prink函数打印的内容属于内核消息。内核消息根据消息的轻重缓急给他们设置不同的消息级别。终端也会存在一个默认的消息级别,只有消息级别高于终端默认消息级别,消息才可以在终端进行输出,消息级别共分为0-7总共8级,数字越小代表消息级别越高,一般常用3-7级 

#define KERN_EMERG         KERN_SOH "0"         /* system is unusable */

#define KERN_ALERT         KERN_SOH "1"         /* action must be taken immediately */

#define KERN_CRIT         KERN_SOH "2"         /* critical conditions */

#define KERN_ERR         KERN_SOH "3"         /* error conditions */

#define KERN_WARNING         KERN_SOH "4"         /* warning conditions */

#define KERN_NOTICE         KERN_SOH "5"         /* normal but significant condition */

#define KERN_INFO         KERN_SOH "6"         /* informational */

#define KERN_DEBUG         KERN_SOH "7"         /* debug-level messages */

 3.查看消息默认级别

        消息默认级别保存在/proc/sys/kernel/printk文件

        查看cat /proc/sys/kernel/printk

        4        4        1        7

        4        终端默认消息级别

        4        printk默认的消息级别

        1        终端支持的消息最高级别

        7        终端支持的消息最低级别

代码示例

#include <linux/init.h>
#include <linux/module.h>// 入口函数,安装内核模块时执行
static int __init mycdev_init(void)
{// static 修饰当前函数只能在本文件使用// int 函数的返回值类型,如果函数规定返回值但是没有加返回值,编译会报错// mycdev_init函数名,可以自己起名字// void表示函数无参数,当没有参数时void一定要加,不然报错//__init的作用是用来告诉编译器当前代码保存在.init.text段中// #define __init       __section(".init.text")// linux内核也会有自己的链接脚本  vmlinux.lds,这个链接脚本里规定了不同的内容在// 内存中的什么位置printk(KERN_ERR "hello world\n");int a=10;printk(KERN_ERR "%d\n",a);return 0;
}
// 出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{// #define __exit       __section(".exit.text")//__exit指定出口函数保存在.exit.text段中
}
// 用于声明入口函数
module_init(mycdev_init);
// 用于声明出口函数
module_exit(mycdev_exit);
// 声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

 5.如何修改消息默认级别

        ubuntu:

                先切换到管理员:sudo su

                再输入以下内容:echo 4 3 1 7 >  /proc/sys/kernel/printk

                注:这种修改方式ubuntn重启后,级别恢复默认设置的4 4 1 7

        开发板上linux

                进入根文件系统下的etc下的init.d文件夹:cd ~/nfs/rootfs/etc/init.d

                打开rcS脚本文件:vi   rcS

                在rcS中最后一行添加:echo 4 3 1 7 > /proc/sys/kernel/printk

6.ubuntu虚拟终端的使用

        切换到虚拟终端:ctrl+alt+[f2-f6](fn)

        退出虚拟终端:ctrl+alt+f1(fn)

7.dmesg命令的使用

        dmesg:查看内核打印消息

        dmesg -c:先将保存的内核消息打印在终端再清除

        dmesg -C:直接清除

相关文章:

驱动:驱动相关概念,内核模块编程,内核消息打印printk函数的使用

一、驱动相关概念 1.操作系统的功能 向下管理硬件&#xff0c;向上提供接口 操作系统向上提供的接口类型&#xff1a; 内存管理&#xff1a;内存申请&#xff08;malloc&#xff09; 内存释放&#xff08;free&#xff09;等 文件管理&#xff1a; 通过文件系统格式对文件ext2…...

【Qt控件之QListWidget】介绍及使用,利用QListWidget、QToolButton、和布局控件实现抽屉式组合控件

概述 QListWidget类提供了基于项目的列表小部件。 QListWidget是一个方便的类&#xff0c;类似于QListView提供的列表视图&#xff0c;但使用经典的基于项目的接口来添加和删除项目。QListWidget使用内部模型来管理列表中的每个QListWidgetItem。 对于更灵活的列表视图小部件…...

【Java基础面试二十四】、String类有哪些方法?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;String类有哪些方法&…...

[DRAFT] LLVM ThinLTO原理分析

我们在《论文阅读&#xff1a;ThinLTO: Scalable and Incremental LTO》中介绍了ThinLTO论文的主要思想&#xff0c;这里我们介绍下LLVM ThinLTO是如何实现的。本文主要分为如下几个部分&#xff1a; LLVM ThinLTO Object 含有哪些内容&#xff1f;LLVM ThinLTO 是如何做优化的…...

使用Gitlab构建简单流水线CI/CD

什么是Gitlab Gitlab实质上是一套DevOps工具 目前看起来&#xff0c;Gitlab属于是内嵌了一套CI/CD的框架&#xff0c;并且可以提供软件开发中的版本管理、项目管理等等其他功能。 这里需要辨别一下Gitlab和Github Gitee的区别。 GIthub大家都很熟悉了&#xff0c;一般大家都会…...

【AIGC核心技术剖析】用于高效 3D 内容创建生成(从单视图图像生成高质量的纹理网格)

3D 内容创建的最新进展主要利用通过分数蒸馏抽样 &#xff08;SDS&#xff09; 生成的基于优化的 3D 生成。尽管已经显示出有希望的结果&#xff0c;但这些方法通常存在每个样本优化缓慢的问题&#xff0c;限制了它们的实际应用。在本文中&#xff0c;我们提出了DreamGaussian&…...

nginx平滑升级添加echo模块、localtion配置、rewrite配置

nginx平滑升级添加echo模块、location配置、rewrite配置 文章目录 nginx平滑升级添加echo模块、location配置、rewrite配置1.环境说明&#xff1a;2.nginx平滑升级原理&#xff1a;3.平滑升级nginx&#xff0c;并添加echo模块3.1.查看当前nginx版本以及老版本编译参数信息3.2.下…...

系统架构师备考倒计时19天(每日知识点)

软件架构评估&#xff08;ATAM&#xff09; 在SAAM的基础上发展起来的&#xff0c;主要针对性能、实用性、安全性和可修改性&#xff0c;在系统开发之前&#xff0c;对这些质量属性进行评价和折中。ATAM方法的主要活动领域包括&#xff1a; 第一阶段 场景和需求收集 收集场景…...

谈谈 Redis 如何来实现分布式锁

谈谈 Redis 如何来实现分布式锁 基于 setnx 可以实现&#xff0c;但是不是可重入的。 基于 Hash 数据类型 Lua脚本 可以实现可重入的分布式锁。 获取锁的 Lua 脚本&#xff1a; 释放锁的 Lua 脚本&#xff1a; 但是还是存在分布式问题&#xff0c;比如说&#xff0c;一个客…...

.NET 6.0 Web API Hangfire

Hangfire 文档 Hangfire 中文文档 Hangfire GitHub使用示例源码 在线Cron表达式生成器 ● Hangfire允许您以非常简单但可靠的方式在请求管道之外启动方法调用。 这种 后台线程 中执行方法的行为称为 后台任务。 ● 它是由:客户端、作业存储、服务端 组成的。 ● Hangfire可以在…...

基于java的校园论坛系统,ssm+jsp,Mysql数据库,前台用户+后台管理,完美运行,有一万多字论文

目录 演示视频 基本介绍 论文目录 功能架构 系统截图 演示视频 基本介绍 基于java的校园论坛系统&#xff0c;Mysql数据库&#xff0c;系统整体采用ssmjsp设计&#xff0c;前台用户后台管理&#xff0c;完美运行&#xff0c;有一万多字论文。 用户功能&#xff1a; 1.系统…...

Django小白开发指南

文章目录 HTTP协议socket实现一个web服务器WSGI实现一个web服务器WSGI实现支持多URL的web服务器WSGI实现图片显示的web服务器MVC && MTV1.MVC2.MTV3.总结 一、创建Django项目1.创建项目2.创建app3.第一次django 请求 二、模板1.配置settings.py2.模板语法3.继承模板 三…...

保序回归与金融时序数据

保序回归在回归问题中的作用是通过拟合一个单调递增或递减的函数&#xff0c;来保持数据点的相对顺序特性。 一、保序回归的作用 主要用于以下情况&#xff1a; 1. 有序数据&#xff1a;当输入数据具有特定的顺序关系时&#xff0c;保序回归可以帮助保持这种顺序关系。例如&…...

基于单片机设计的家用自来水水质监测装置

一、前言 本文介绍基于单片机设计的家用自来水水质监测装置。利用STM32F103ZET6作为主控芯片&#xff0c;结合水质传感器和ADC模块&#xff0c;实现对自来水水质的检测和监测功能。通过0.96寸OLED显示屏&#xff0c;将采集到的水质数据以直观的方式展示给用户。 随着人们对健…...

ubuntu20.04运用startup application开机自启动python程序

运用startup application开机自启动python程序。在终端中输入gnome-session-properties,如果显示没有则先进行安装&#xff0c;sudo apt-get update 和sudo apt install StartupApplications(根据显示提示安装)。在显示程序中搜索startup&#xff0c;打开应用程序。 在程序目录…...

SpringBoot整合Caffeine实现缓存

Caffeine Caffeine是一种基于Java的高性能缓存库&#xff0c;它提供了可配置、快速、灵活的缓存实现。Caffeine具有以下特点&#xff1a; 高性能&#xff1a;Caffeine使用了一些优化技术&#xff0c;如基于链表的并发哈希表和无锁算法&#xff0c;以提供卓越的读写性能。容量…...

DVWA-弱会话IDS

弱会话IDS Session简介&#xff1a; 用户登录后&#xff0c;在服务器就会创建一个会话(session)&#xff0c;叫做会话控制&#xff0c;接着访问页面的时候就不用登录&#xff0c;只需要携带Session去访问即可。 sessionID作为特定用户访问站点所需要的唯一内容。如果能够计算…...

【C++中cin、cin.get()、cin.getline()、getline() 的区别】

文章目录 引入cin基本用法输入多个变量换行符存放在缓冲区中 cin.get()基本用法重载函数换行符残留在缓冲区中 cin.getline()基本使用重载函数换行符不会残留在缓冲区中 string 流中的 getline()总结用法总结几个输入实例输入格式输入格式输入格式输入格式 输出格式 写在最后 引…...

SSH连接华为交换机慢

ssh连接交换机慢是因为交换计算密钥算法阶段默认使用安全性更高的秘钥&#xff0c;由于性能问题导致连接比较慢&#xff0c;如一台华为S5735S-L24T4S-QA2的交换机默认使用如下秘钥&#xff0c;安全行由高到低。 ssh server key-exchange dh_group16_sha512 dh_group15_sha512 …...

Web攻防03_MySQL注入_数据请求

文章目录 PHP-MYSQL-数据请求类型1、数字型(无符号干扰)2、字符型&#xff08;有符号干扰&#xff09;3、搜索型&#xff08;有多符号干扰&#xff09;4、框架型&#xff08;有各种符号干扰&#xff09; PHP-MYSQL-数据请求方法数据请求方法GET&#xff1a;POST&#xff1a;Coo…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...