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

ubuntu下调试驱动

使用 Ubuntu Linux 测试 Linux 驱动

1. 测试 Linux 驱动准备工作

​ 对于一个 Linux 驱动程序,一开始可以在 Ubuntu Linux 上做前期开发和测试。对于访问硬件部分也可以在 Ubuntu Linux 用软件进行模拟,切记不能代替真实的环境!当基本开发完成后,就需要在开发板或工程样机上使 用真实的硬件进行测试,当然,最后还需要在最终销售的产品上进行测试。最终测试通过,Linux 驱动才能算真 正开发完成。

1.1 实现步骤

1)先测试自己 ubuntu 虚拟机的版本号

sun@ubuntu:~$ uname -r

2)找到对应版本的内核源码编译的目录:

sun@ubuntu:/lib/modules$ ls
5.15.0-43-generic  5.15.0-56-generic  5.19.0-32-generic
5.15.0-53-generic  5.15.0-60-generic  5.19.0-35-genericsun@ubuntu:/lib/modules$ cd 5.19.0-32-generic
sun@ubuntu:/lib/modules/5.19.0-32-generic$ ls
build              modules.builtin.alias.bin  modules.order
initrd             modules.builtin.bin        modules.softdep
kernel             modules.builtin.modinfo    modules.symbols
modules.alias      modules.dep                modules.symbols.bin
modules.alias.bin  modules.dep.bin            vdso
modules.builtin    modules.devnamesun@ubuntu:/lib/modules/5.19.0-32-generic$ cd build
sun@ubuntu:/lib/modules/5.19.0-32-generic/build$ ls
arch    Documentation  init      Kconfig   mm              scripts   ubuntu
block   drivers        io_uring  kernel    Module.symvers  security  usr
certs   fs             ipc       lib       net             sound     virt
crypto  include        Kbuild    Makefile  samples   

3)修改测试驱动程序的 Makefile 文件

KERNEL_DIR = /lib/modules/5.19.0-32-generic/build #ubuntu 内核目录
CUR_DIR = $(shell pwd)
MYAPP = virtdev_test
all:make -C $(KERNEL_DIR) M=$(CUR_DIR) modulesgcc -o $(MYAPP) $(MYAPP).c
clean:make -C $(KERNEL_DIR) M=$(CUR_DIR) cleanrm -rf $(MYAPP)
obj-m = virtdev_drv.o

2. 测试驱动程序

2.1 编写驱动程序 virtdev_drv.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
// 定义设备文件名
#define DEVICE_NAME "virtdev"
static int atom = 0;
// 参数 atom=0: 多个进程可以同时打开 vritdev 设备文件
// 参数 atom 非 0:同时只能有一个进程打开 virtdev 设备文件
static atomic_t int_atomic_available = ATOMIC_INIT(1);
// 原子变量值为 1
static int virtdev_open(struct inode *node, struct file *file)
{if (atom){if (!atomic_dec_and_test(&int_atomic_available)){atomic_inc(&int_atomic_available);return -EBUSY;}}return 0;
}static int virtdev_close(struct inode *node, struct file *file)
{if (atom){atomic_inc(&int_atomic_available);}return 0;
}static struct file_operations dev_fops =
{.owner = THIS_MODULE,.open = virtdev_open,.release = virtdev_close
};static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops
};// 初始化 Linux 驱动
static int __init virtdev_init(void)
{// 建立设备文件int ret = misc_register(&misc);printk("<jaylen> atomic=%d\n", atom);printk("virtdev_init_success\n");return ret;
}// 卸载 Linux 驱动
static void __exit virtdev_exit(void)
{printk("<jaylen> atomic=%d\n", atom);printk("<jaylen> virtdev_exit_success\n");// 删除设备文件misc_deregister(&misc);
}// 注册初始化 Linux 驱动的函数
module_init(virtdev_init);
// 注册卸载 Linux 驱动的函数
module_exit(virtdev_exit);module_param(atom, int, S_IRUGO | S_IWUSR);
MODULE_LICENSE("GPL");

2.2 编写应用程序 virtdev_test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{printf("app pid=%d is running\n", getpid());int fd = open("/dev/virtdev", O_RDWR);printf("ret:%d\n", fd);if (fd < 0){printf("errno:%d\n", errno);}else{sleep(10);close(fd);}printf("app pid=%d is over\n", getpid());return 0;
}

2.3 编译驱动

在 ubuntu 普通用户下完成编译驱动

un@ubuntu:ubuntu_drv_test$ make
make -C /lib/modules/5.19.0-32-generic/build M=/home/sun/work/ubuntu_drv_test modules
make[1]: 进入目录“/usr/src/linux-headers-5.19.0-32-generic”
warning: the compiler differs from the one used to build the kernelThe kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0You are using:           gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0CC [M]  /home/sun/work/ubuntu_drv_test/virtdev_drv.oMODPOST /home/sun/work/ubuntu_drv_test/Module.symversCC [M]  /home/sun/work/ubuntu_drv_test/virtdev_drv.mod.oLD [M]  /home/sun/work/ubuntu_drv_test/virtdev_drv.koBTF [M] /home/sun/work/ubuntu_drv_test/virtdev_drv.ko
Skipping BTF generation for /home/sun/work/ubuntu_drv_test/virtdev_drv.ko due to unavailability of vmlinux
make[1]: 离开目录“/usr/src/linux-headers-5.19.0-32-generic”
gcc -o virtdev_test virtdev_test.c

1.2.4 测试驱动

在 ubuntu 下需要切换到管理员用户下才能安装测试驱动

sun@ubuntu:ubuntu_drv_test$ sudo su
root@ubuntu:/home/sun/work/ubuntu_drv_test# ls
hello_test     Module.symvers  virtdev_drv.mod    virtdev_drv.o
Makefile       virtdev_drv.c   virtdev_drv.mod.c  virtdev_test
modules.order  virtdev_drv.ko  virtdev_drv.mod.o  virtdev_test.c

安装驱动

root@ubuntu:/home/sun/work/ubuntu_drv_test# insmod virtdev_drv.ko 

传参加载驱动

root@ubuntu:/home/sun/work/ubuntu_drv_test# insmod virtdev_drv.ko atom=1

打印并清空缓冲区日志 dmesg -c, 以下是测试过程

驱动加载过程

root@ubuntu:/home/sun/work/ubuntu_drv_test# dmesg
[25849.067381] <robin> atomic=0
[25849.067387] <robin> virtdev_exit_success
[25867.980387] <robin> atomic=1
[25867.980395] virtdev_init_successroot@ubuntu:/home/sun/work/ubuntu_drv_test# lsmod
Module                  Size  Used by
virtdev_drv            16384  1root@ubuntu:/home/sun/work/ubuntu_drv_test# ls /dev/virtdev -al
crw------- 1 root root 10, 121  3月 11 22:14 /dev/virtdev

用户测试

sun@ubuntu:ubuntu_drv_test$ sudo ./virtdev_test 
app pid=43934 is running
ret:3
app pid=43934 is over

驱动卸载

root@ubuntu:/home/sun/work/ubuntu_drv_test# rmmod virtdev_drv
root@ubuntu:/home/sun/work/ubuntu_drv_test# dmesg 
[25849.067381] <robin> atomic=0
[25849.067387] <robin> virtdev_exit_success
[25867.980387] <robin> atomic=1
[25867.980395] virtdev_init_success
[26054.089448] <robin> atomic=1
[26054.089456] <robin> virtdev_exit_success

3 Linux 内核日志查看之 dmesg 命令简介

Linux 内核启动时会加载硬件驱动,在有新硬件时也会加载驱动,如果想要查看内核的活动,可以使用 dmesg 命令。Linux 内核日志存储在一个 ring-buffer 中,它的大小是固定的,当队列满时,新的消息会覆盖掉最旧的消 息。实际上,在 boot 阶段,所有的应用还没有启动,syslogd 也未启动,这时内核日志是非常重要的信息。 除了设备初始化日志、内核模块日志,它还会包含一些应用崩溃的相关信息记录,了解 dmesg 的使用对于调 试程序相当重要。

对于嵌入式设备的调试,它会比较清楚地展现当前的 log 信息。 dmesg -c 显示并清除当前的日志内容。 下次再 dmesg 时就没有以前的日志了。

相关文章:

ubuntu下调试驱动

使用 Ubuntu Linux 测试 Linux 驱动 1. 测试 Linux 驱动准备工作 ​ 对于一个 Linux 驱动程序&#xff0c;一开始可以在 Ubuntu Linux 上做前期开发和测试。对于访问硬件部分也可以在 Ubuntu Linux 用软件进行模拟,切记不能代替真实的环境&#xff01;当基本开发完成后&#…...

第十四届蓝桥杯三月真题刷题训练——第 9 天

第 1 题&#xff1a;找素数 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 素数就是不能再进行等分的整数。比如&#xff1a;7&#xff0c;11。而 9 不是素数&#xff0c;因为它可以平分为 3 等份。一般认为最小的…...

操作系统复习

熟练掌握操作系统的定义&#xff0c;操作系统的特征&#xff0c;操作系统的功能熟练掌握多道程序设计的概念&#xff0c;单道程序设计和多道程序设计的区别&#xff0c;多道程序设计的优点熟悉操作系统接口的主要功能&#xff0c;系统调用的基本概念、类型、实现。操作系统接口…...

springboot健身房管理系统

springboot健身房管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xf…...

C语言学习笔记——数组

前言 数组是C语言中的一种自定义数据类型&#xff0c;它的使用非常广泛。但是很多新手在使用数组时&#xff0c;经常在一些细节上出问题&#xff0c;导致程序崩溃或者无法编译。今天&#xff0c;我就来详细聊聊数组的使用和我注意到的一些细节。 一、常见的数组类型与数组的创建…...

类和对象 - 中

本文已收录至《C语言》专栏&#xff01; 作者&#xff1a;ARMCSKGT 目录 前言 正文 构造函数 对比C和C的初始化 构造函数的使用与特性 默认构造函数 C11关于默认构造缺陷的补丁 析构函数 析构函数特性 默认析构和自定义析构 拷贝构造函数 问题聚焦 拷贝构造的定…...

Android之屏幕适配方案

在说明适配方案之前&#xff0c;我们需要对如下几个概念有所了解&#xff1a;屏幕尺寸&#xff0c;屏幕分辨率&#xff0c;屏幕像素密度。 屏幕尺寸 屏幕尺寸指屏幕的对角线的物理长度&#xff0c;单位是英寸&#xff0c;1英寸2.54厘米。 比如常见的屏幕尺寸&#xff1a;5.0、5…...

SpringBoot+jersey跨域文件上传

一、配置tomcat服务器 1.1、添加upload文件夹 在webapps\Root文件夹下创建用于接收上传文件的upload文件夹 1.2、修改conf\web.xml设置允许上传文件 <init-param><param-name>readonly</param-name><param-value>false</param-value></ini…...

数据结构One——绪论

本喵是FW视频封面最终版宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#…...

JVM篇之内存及GC

目录一、JVM内存区域1.1程序计数器1.2虚拟机栈1.3本地方法栈1.4堆1.5方法区二、JVM运行时内存2.1新生代(轻量级GC)2.2老年代&#xff08;重量级GC&#xff09;一、JVM内存区域 JVM 内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法栈】、线程共享区域【JAVA 堆、…...

Linux驱动操作地址(寄存器)的一些方式

Linux驱动操作地址(寄存器&#xff09;的一些方式 文章目录Linux驱动操作地址(寄存器&#xff09;的一些方式1.对绝对地址赋值操作2. ioremap2.1 void __iomem *地址2.2 volatile unsigned int *地址2.3 structioremap1.对绝对地址赋值操作 对绝对地址0x100000赋值操作 *&…...

Java日志框架介绍

Log4j Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Glc首创的&#xff0c;现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。 Log4j 2 Apache Log4j 2是apache开发的一款Log4j的升级产品。 Commons Logging Apache基金会所属的项目&#xff0c;是…...

编程中遇到的计算机大小端概念

概念大小端&#xff08;Endian&#xff09;是指在一个多字节的数据中&#xff0c;字节的存储顺序的规定。通俗来说&#xff0c;就是指数据在计算机内部存储时的顺序问题。在计算机系统中&#xff0c;一个数据项可能占据多个存储单元。在这种情况下&#xff0c;这个数据项的存储…...

日志与可视化方案:从ELK到EFK,再到ClickHouse

EFK方案 从ELK谈起 ELK是三个开源软件的缩写&#xff0c;分别表示&#xff1a;Elasticsearch&#xff0c;Logstash&#xff0c;Kibana。新增了一个FlieBeat&#xff0c;它是一个轻量级的日志收集处理工具&#xff0c;FlieBeat占用资源少&#xff0c;适用于在各个服务器上搜集…...

字符函数和字符串函数(上)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰来给大家介绍一个全新的知识点&#xff0c;就是字符函数和字符串函数啦&#xff0c;其实其中有些函数我之前已经学习过了&#xff0c;比如strlen、strcpy&#xff1b;也有一些之前不是很熟悉的函数&#xff0c;比如strstr、strtok…...

九龙证券|下周解禁市值超400亿元,3股解禁压力较大

下周3股解禁比例超50%。 百利电气昨日盘中直线拉升封板&#xff0c;至此&#xff0c;百利电气两连板&#xff0c;累计涨幅20.85%。 昨日晚间&#xff0c;百利电气发布股票交易反常动摇公告称&#xff0c;公司不触及“室温超导”相关业务&#xff0c;也未打开相关研发和投入。公…...

一个大型网站架构的演变历程

正序&#xff1a; Rome was not built in a day&#xff08;罗马不是一天建成的。&#xff09;一个成熟的大型网站从来都不是一蹴而就的&#xff0c;需要经过多次架构的调整和升级&#xff0c;我们熟知的大型网站比如京东、淘宝、亚马逊&#xff0c;它们每天都有巨大的用户访问…...

前端前沿web 3d可视化技术 ThreeJS学习全记录

前端前沿web 3d可视化技术 随着浏览器性能和网络带宽的提升 使得3D技术不再是桌面的专利 打破传统平面展示模式 前端方向主要流向的3D图形库包括Three.js和WebGL WebGL灵活高性能&#xff0c;但代码量大&#xff0c;难度大&#xff0c;需要掌握很多底层知识和数学知识 Threej…...

链表经典笔试题(LeetCode刷题)

本篇文章主要是对力扣和牛客网上一些经典的和链表有关的笔试题的总结归纳&#xff0c;希望对你有所帮助。 目录 一、移除链表元素 1.1 问题描述 1.2 思路一 1.2.1 分析 1.2.2 代码 1.3 思路二 1.3.1 分析 1.2.3 思路三 1.3 代码实现 1.3.1 思路1的代码 1.3.2 思路2的…...

SpringCloud五大组件

微服务SpringCloud整合技术组件基本流程&#xff1a; 引入组件启动器依赖坐标覆盖默认配置即application.properties配置文件(每个微服务只有一个并且服务启动默认加载)引导类(微服务入口即main方法)自定义开启组件注解 SpringCloudEureka 服务注册中心&#xff0c;分为Eure…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...