驱动:驱动相关概念,内核模块编程,内核消息打印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:直接清除

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

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

相关文章

E054-web安全应用-Brute force暴力破解进阶

课程名称&#xff1a; E054-web安全应用-Brute force暴力破解进阶 课程分类&#xff1a; web安全应用 实验等级: 中级 任务场景: 【任务场景】 小王接到磐石公司的邀请&#xff0c;对该公司旗下的网站进行安全检测&#xff0c;经过一番检查发现该网站可能存在弱口令漏洞…

AAOS CarMediaService 服务框架

文章目录 前言MediaSessionCarMediaService作用是什么&#xff1f;提供了哪些接口&#xff1f;如何使用&#xff1f;CarMediaService的实现总结 前言 CarMediaService 是AAOS中统一管理媒体播放控制、信息显示和用户交互等功能的服务。这一服务依赖于android MediaSession框架…

搭建NGINX服务 如何统计网页访问量

一、搭建Nginx服务 搭建之前需要查看一下我们的内核数制 我们进行简单的内核优化 命令&#xff1a;ulimit -n 65535 安装Nginx服务 第一步 关闭防火墙和安全机制 systemctl stop firewalld #关闭防火墙 systemct disable firewalld #开机自动关闭防火墙 setenfor…

美创科技信创数据安全「利基者」!

近日&#xff0c;第一新声研究部正式发布《2023年中国信创网络安全产品竞争力象限》&#xff08;下称“象限报告“&#xff09;。 ◼︎ 象限报告综合考虑企业占有率、在技术/应用上的成熟度、在客户方面的交付完成度及口碑、产品在市场/营销/商业模式/行业拓展等战略上的领先性…

无人机新手防炸飞行技巧

不要在室内飞行,容易撞墙。起飞前设置好避障和返航模式。使用模拟器熟练掌握操控。选择开阔环境目视起飞。使用低速档平稳飞行。合理使用避障功能,不要盲目依赖。使用九宫格避障法。留意电量,及时返航。极低电量时放弃强行返航。飞行后及时为电池充电保养。

文件管理系统的基本认识

1.文件的属性 文件的定义:一组有意义的信息的集合。 1.文件名: 由创建文件的用户决定文件名&#xff0c;主要是为了方便用户找到文件&#xff0c;同一目录下不允许有重名文件。 2.标识符: 一个系统内的各文件标识符唯一&#xff0c;对用户来说毫无可读性&#xff0c; 因此…

NetCore/Net8下使用Redis的分布式锁实现秒杀功能

目的 本文主要是使用NetCore/Net8加上Redis来实现一个简单的秒杀功能&#xff0c;学习Redis的分布式锁功能。 准备工作 1.Visual Studio 2022开发工具 2.Redis集群&#xff08;6个Redis实例&#xff0c;3主3从&#xff09;或者单个Redis实例也可以。 实现思路 1.秒杀开始…

mysql按照日期分组统计数据(date_formatstr_to_date)

学习链接 mysql按照日期分组统计数据 博主-山茶花开时的 【Mysql专栏学习】 mysql按照日期分组统计数据 Mysql的date_format函数想必大家都使用过吧&#xff0c;一般用于日期时间转化&#xff0c;如下所示 # 可以得出 2023-01-01 08:30:50 select DATE_FORMAT(2023-01-01…

【合宙Air700E/780E短信转发】短信转发移动联通 不要钉钉不要微信,转发自建服务器-傻瓜式搭建

官方提供的教程介绍了通过钉钉、微信等工具接收短信验证码的方法&#xff0c;但最终实现的目的是获取验证码&#xff0c;而不是通过工具间接获得。 因此&#xff0c;我们可以直接调用API接口来获取验证码&#xff0c;从而达到更快、更便捷地获得验证码的目的。 所以做了一个服…

STM32内部flash闪存的总结

最近在做无人船和机巢远程在线升级的项目&#xff0c;牵扯到flash的操作&#xff0c;特此记录&#xff0c;便于以后查找。IMU也用到过&#xff0c;当时没记录 具体细节看 E:\Documets\AY\a-project\IMU\IMU16500\S0IMU v3.3 study\User\Driver\source eeprom.c E:\Documets\A…

【Java基础面试三十四】、接口中可以有构造函数吗?

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

mysql检验分区性能的操作

mysql检验分区性能的操作 创建两个结构相同但是一个有分区另外一个没有分区的表 如上图我们给part_tab5创建的分区为1024个&#xff0c;因为mysql中允许最多有1024个分区&#xff1b;之前我测试的是创建8个分区&#xff0c;然后插入500万条数据&#xff0c;然后按照id查询&…

【持续更新】tutorial-Linux-Markdown-etc(Linux、命令、Markdown、md、Tex、LaTex)

1. Linux命令 1.1 常用 查看文件夹下文件数量: ls -l | wc -l7zip: 解压&#xff1a;7z x compressed_file.7z -o/path/to/destination # 注意-o和目标路径是连起来的&#xff0c;没有空格压缩&#xff1a;7z a compressed_file.zip destination_path conda 查看 conda 拥有的…

浏览器调试模式获取链接信息(获取京东cookie为例)

通过浏览器的调试模式&#xff0c;获取京东cookie变量pt_pin和pt_key。 一、登录 1&#xff09;打开网页 浏览器打开手机版京东网页&#xff1a;m.jd.com 2&#xff09;登录账号 点击【登录】按钮&#xff0c;输入账号密码登录 二、调试模式 1&#xff09;停留在要调试的…

C/C++ 快速入门

参考&#xff1a;https://blog.csdn.net/gao_zhennan/article/details/128769439 1 下载Visual Studio Code并安装中文插件&#xff0c;此处不再叙述 2 插件安装C/C插件 3 使用快捷键【Ctr ~】打打开终端 验证并未安装编译器 4 我们即将使用【MinGW-64】做为编译器 https:…

[nlp] chathome—家居装修垂类大语言模型的开发和评估

ChatHome: Development and Evaluation of a Domain-Specific LanguageModel for Home Renovation ChatHome: 家居装修垂类大语言模型的开发和评估 1、摘要: 我们的方法包括两个步骤:首先,使用广泛的家庭装修数据集(包括专业文章、标准文档和网络内容)对通用模型进行后预训…

C/C++面试常见问题——指针和引用的区别

首先想要理解指针和引用的区别&#xff0c;我们要明确什么是指针&#xff0c;什么是引用 一&#xff0c;指针和引用的基本概念及特性 指针是一个特殊变量&#xff0c;其中存储着所指向变量的地址 指针主要有以下特性&#xff1a; 1. 在使用时需要*解引用 2. sizeof(指针)的…

ChatGPT/GPT4科研技术应用与AI绘图及论文高效写作

2023年我们进入了AI2.0时代。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车&#xff0c;就有可能被淘汰在这个数字化时代&#xff0c;如何能高效地处理文本、文献查阅、PPT…

大数据中间件——Kafka

Kafka安装配置 首先我们把kafka的安装包上传到虚拟机中&#xff1a; 解压到对应的目录并修改对应的文件名&#xff1a; 首先我们来到kafka的config目录&#xff0c;我们第一个要修改的文件就是server.properties文件&#xff0c;修改内容如下&#xff1a; # Licensed to the …

从Github中下载部分文件

我们经常回去Github中下载代码&#xff0c;但仓库中存在很多project代码。但我们如果只需要某一个或几个项目的代码&#xff0c;此时应该如何操作呢&#xff1f; 这里介绍两款工具&#xff0c;可以从仓库中下载部分文件的小工具: DownGit 和 GitZip 1. DownGit downGit 国内镜…