Linux内核gcov修改为模块
Linux内核gcov修改为模块
Gcov 是 GNU 项目开发的代码覆盖率分析工具,与 GCC 编译器深度集成,用于统计程序运行时代码的执行情况,帮助开发者评估测试用例的完整性和代码质量。
Gcov工作原理
1. 编译插桩
编译时需添加 -fprofile-arcs -ftest-coverage
选项,GCC 会在代码中插入统计逻辑:
- .gcno 文件:记录基本块(Basic Block)的图结构和源码行号信息。
- **.gcda 文件**:运行时生成,存储实际执行路径的计数数据(如弧跳变次数)。
- 数据收集与分析
- 运行程序后(一定是调用gcc exit退出的,不能是被SIGINT等信号杀死),.gcda 文件生成于可执行文件所在目录。
- 执行 gcov <源文件> 命令,解析 .gcno 和 .gcda 文件,生成 .gcov 文本报告
内核从2.6.31 开始,Gcov 支持被合并到内核主线。通过下面两个配置选项开启:
CONFIG_GCOV_KERNEL=y # 启用内核 Gcov 支持
CONFIG_GCOV_PROFILE_ALL=y # 统计整个内核的覆盖率
由于性能开销、资源占用、安全性和维护成本等几方面考虑,普通Linux发行版并不会打开此配置,如果想要统计测试覆盖率,只能自己重新编译内核,费时费力。
最近琢磨了一下把gcov做成模块,用户可以根据需要自行加载,挺有用的还,记录一下。
我们先实现一个hello_world
测试模块,创建一个char设备,然后用户通过ioctl操作这个设备。下面是代码:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>#define DEVICE_NAME "hello_ioctl"
#define CLASS_NAME "hello_class"// 设备操作函数声明
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char __user *, size_t, loff_t *);// 文件操作结构体
static struct file_operations fops = {.open = device_open,.release = device_release,.read = device_read,.write = device_write,
};// 设备号和类指针
static dev_t dev_num;
static struct class *hello_class = NULL;
static struct cdev hello_cdev;// 设备打开函数
static int device_open(struct inode *inode, struct file *file) {printk(KERN_INFO "Device opened\n");return 0;
}// 设备关闭函数
static int device_release(struct inode *inode, struct file *file) {printk(KERN_INFO "Device closed\n");return 0;
}// 设备读取函数
static ssize_t device_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {printk(KERN_INFO "Device read\n");return 0;
}// 设备写入函数
static ssize_t device_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) {printk(KERN_INFO "Device write\n");return len;
}// 模块初始化函数
static int __init hello_init(void) {int ret;// 动态分配设备号ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);if (ret < 0) {printk(KERN_ERR "Failed to allocate device number\n");return ret;}// 创建设备类hello_class = class_create(THIS_MODULE, CLASS_NAME);if (IS_ERR(hello_class)) {unregister_chrdev_region(dev_num, 1);printk(KERN_ERR "Failed to create device class\n");return PTR_ERR(hello_class);}// 初始化并注册字符设备cdev_init(&hello_cdev, &fops);hello_cdev.owner = THIS_MODULE;ret = cdev_add(&hello_cdev, dev_num, 1);if (ret < 0) {class_destroy(hello_class);unregister_chrdev_region(dev_num, 1);printk(KERN_ERR "Failed to add cdev\n");return ret;}// 创建设备节点(触发udev自动创建/dev/hello_ioctl)device_create(hello_class, NULL, dev_num, NULL, DEVICE_NAME);printk(KERN_INFO "Device created successfully at /dev/%s\n", DEVICE_NAME);return 0;
}// 模块卸载函数
static void __exit hello_exit(void) {// 销毁设备节点device_destroy(hello_class, dev_num);// 销毁设备类class_destroy(hello_class);// 删除字符设备cdev_del(&hello_cdev);// 释放设备号unregister_chrdev_region(dev_num, 1);printk(KERN_INFO "Driver exited successfully\n");
}module_init(hello_init);
module_exit(hello_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("YourName");
MODULE_DESCRIPTION("A simple character device driver demo");
MODULE_VERSION("1.0");
设备读写函数比较简单,都是往dmesg打印一行内容。仅仅是为了测试gcov统计代码调用次数的。这是Makefile
# Makefile内容
obj-m += helloworld.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
下面是用户态调用ioctl:
// 示例测试程序(test.c)
#include <stdio.h>
#include <fcntl.h>int main() {int fd = open("/dev/hello_ioctl", O_RDWR);if (fd < 0) {perror("Failed to open device");return -1;}write(fd, "test", 4);close(fd);return 0;
}
先测试一下基本功能,insmod之后ls /dev/hello_ioctl
设备存在,然后编译运行test.c
,dmesg能看到下面这些信息。
假定说test.c是测试helloworld.ko的用例,运行完后,我想知道ko模块多少代码被调用到了。gcov就提供了这个功能呢,按照前文,需要现在makefile里添加编译参数
ccflags-y += -fprofile-arcs -ftest-coverage
j
插桩完成后,make编译会提示
ERROR: modpost: "__gcov_merge_add" undefined!
ERROR: modpost: "__gcov_exit" undefined!
ERROR: modpost: "__gcov_init" undefined!
这是因为gcc会接在插入一段代码,调用到这几个函数,但是内核符号表里面又找不到这几个。这时候我们需要先把gcov修改为模块,主要就是添加一下module_exit 调用资源卸载回收之类的。写一个makefile,把gcov编译成ko就行。这里面文件太多而杂,就不一一展示了。等编译好gcov.ko
之后,ls Module.symvers
查看gcov符号表。
现在来编译helloworld模块吧,用KBUILD_EXTRA_SYMBOLS
指定extra符号表,这样就不会再报错了。
make KBUILD_EXTRA_SYMBOLS=gcov符号表路径
gcc会在helloworld里面插入一个.init_array
段,readelf时候就能看到:
这是gcc自动插入代码这部分是完成了,接下来只需要调用到init_array
段,这样gcov就完成实现gcov功能了。内核在load_modules->do_init_module->do_mod_ctor
真正执行init_array
的功能,请注意do_mod_ctor
是在执行do_one_initcall
也就是注册好的module_init
之前被调用到的。这个函数主要功能被CONFIG_CONSTRUCTORS
宏框起来了,如果没打开GCOV_KERNEL
的话,内核压根不会编译这块代码。
目前的思路是,通过kprobe分别在find_module_sections
和do_init_module
函数里注入代码,完成init_array段的查找和执行。内核为了安全起见,load_module函数u用到的很多结构和函数定义都是static,没关系在kprobe里照原样再定义一次就行,数据解析出来也是一样的,最终我们只是要init_array
的地址就可以。下面是kprobe代码:
#define pr_fmt(fmt) "%s: " fmt, __func__#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>static char find_symbol[64] = "find_module_sections";
static char init_symbol[64] = "do_init_module";
unsigned int num_ctors; //number of init_array functions
ctor_fn_t *ctors;struct load_info {const char *name;/* pointer to module in temporary copy, freed at end of load_module() */struct module *mod;Elf_Ehdr *hdr;unsigned long len;Elf_Shdr *sechdrs;char *secstrings, *strtab;unsigned long symoffs, stroffs, init_typeoffs, core_typeoffs;struct _ddebug *debug;unsigned int num_debug;bool sig_ok;
#ifdef CONFIG_KALLSYMSunsigned long mod_kallsyms_init_off;
#endifstruct {unsigned int sym, str, mod, vers, info, pcpu;} index;
};struct load_info *info;static struct kprobe kp_find = {.symbol_name = find_symbol,
};
static struct kprobe kp_init = {.symbol_name = init_symbol,
};/* Find a module section: 0 means not found. */
static unsigned int find_sec(const struct load_info *info, const char *name)
{unsigned int i;for (i = 1; i < info->hdr->e_shnum; i++) {Elf_Shdr *shdr = &info->sechdrs[i];/* Alloc bit cleared means "ignore it." */if ((shdr->sh_flags & SHF_ALLOC)&& strcmp(info->secstrings + shdr->sh_name, name) == 0)return i;}return 0;
}/* Find a module section, or NULL. Fill in number of "objects" in section. */
static void *section_objs(const struct load_info *info,const char *name,size_t object_size,unsigned int *num)
{unsigned int sec = find_sec(info, name);/* Section 0 has sh_addr 0 and sh_size 0. */*num = info->sechdrs[sec].sh_size / object_size;return (void *)info->sechdrs[sec].sh_addr;
}static int __kprobes init_handler_pre(struct kprobe *p, struct pt_regs *regs)
{struct module *mod;int i;//X86架构mod = regs->di;if(strcmp("helloworld", mod->name) == 0) {for(i = 0; i < num_ctors; i++) {if(ctors[i])ctors[i]();}}return 0;
}static int __kprobes find_handler_pre(struct kprobe *p, struct pt_regs *regs)
{struct module *mod;unsigned long i;mod = regs->di;info = regs->si;ctors = section_objs(info, ".ctors", sizeof(*ctors), &num_ctors);if(!ctors)ctors = section_objs(info, ".init_array", sizeof(*ctors), &num_ctors);else if(find_sec(info, "init_array")) {pr_warn("%s: has both .ctor and .init_array\n", mod->name);return -EINVAL;}return 0;
}static int __init kprobe_init(void) {int ret;kp_find.pre_handler = find_handler_pre;kp_init.pre_handler = init_handler_pre;ret = register_kprobe(&kp_find);if(ret < 0) {pr_err("register_kprobe find failed, returned %d\n", ret);return ret;}ret = register_kprobe(&kp_init);if(ret < 0) {pr_err("register_kprobe init failed, returned %d\n", ret);return ret;}return 0;
}static void __exit kprobe_exit(void) {unregister_kprobe(&kp_find);pr_info("kprobe at %p unregistered\n", kp_find.addr);unregister_kprobe(&kp_init);pr_info("kprobe at %p unregistered\n", kp_init.addr);
}module_init(kprobe_init);
module_exit(kprobe_exit);
MODULE_LICENSE("GPL");
insmod gcov.ko
执行完成之后,在/sys/kernel/debug
下生成gcov目录,目录下暂时只有一个reset文件,reset文件是后面删除内存中gcov data的,往此文件写入模块名字,可以清除所有data数据,从头开始统计。
插入kprobe和helloworld模块,在sys下会生成对应的路径,等测试用例执行结束后,可以看到data文件,用gcov分析即可得到覆盖率。
相关文章:
Linux内核gcov修改为模块
Linux内核gcov修改为模块 Gcov 是 GNU 项目开发的代码覆盖率分析工具,与 GCC 编译器深度集成,用于统计程序运行时代码的执行情况,帮助开发者评估测试用例的完整性和代码质量。 Gcov工作原理 1. 编译插桩 编译时需添加 -fprofile-arcs -…...
【安装配置教程】linux部署AList记录
之前朋友安利给自己AList,这个工具可以很方便的管理个人的网盘内容,可以随时上传下载拉取,于是心血来潮自己部署并记录一下。 一、拉取下载脚本 在AList官网,找到安装下面的一键脚本 curl -fsSL "https://alist.nn.ci/v3.sh…...
题解:AT_abc245_e [ABC245E] Wrapping Chocolate
我绝对不会告诉你我打比赛时没做出来这道题。 题目简化:给定每个巧克力和盒子的长宽,已知每个盒子只能放一块巧克力,并且必须保证巧克力能放下,求是否所有巧克力都能放入。 思路:贪心、二分、排序、STL。 首先看到这…...
Linux 入门:操作系统进程详解(上)
目录 一.冯诺依曼体系结构 一). 软件运行前为什么要先加载?程序运行之前在哪里? 二).理解数据流动 二.操作系统OS(Operator System) 一).概念 二).设计OS的目的 三).如何理解操作系统…...
5.7/Q1,GBD数据库最新文章解读
文章题目:Global, regional, and national burden and trends of rheumatoid arthritis among the elderly population: an analysis based on the 2021 Global Burden of Disease study DOI:10.3389/fimmu.2025.1547763 中文标题:全球、区域…...
[pdf,epub]292页《分析模式》漫谈合集01-59提供下载
《分析模式》漫谈合集01-59的pdf、epub文件提供下载,地址: umlchina.com/url/ap.html,或查看本账号的CSDN资源。 已排版成适合手机阅读,pdf的排版更好一些。...
Spring MVC的工作流程, DispatcherServlet 的工作流程
Spring MVC 是一种基于Java的模型-视图-控制器(MVC)Web框架,它通过清晰的角色划分简化了Web应用开发。下面是Spring MVC的工作流程以及DispatcherServlet的具体工作流程。 Spring MVC 工作流程 请求到达:客户端发起一个HTTP请求…...
【Godot】使用 Shader 实现可配置圆角效果
文章目录 效果预览实现原理完整Shader代码关键参数详解1. 半径参数(radius)2. 角开关参数(hide_*)数学原理圆形区域判定公式坐标映射性能优化使用示例编辑器操作代码控制进阶技巧1. 添加抗锯齿2. 外发光效果3. 动画效果常见问题解决方案问题1:圆角边缘锯齿问题2:圆形变形…...
【翻译、转载】MCP 提示 (Prompts)
原文地址:https://modelcontextprotocol.io/docs/concepts/prompts#python 提示 (Prompts) 创建可重用的提示模板和工作流 提示 (Prompts) 使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地将其呈现给用户和 LLM。它们提供了一种强大的方式来…...
论快乐的学习和学习的快乐
目录 一、背景二、过程1.快乐的学习:理念与实践快乐学习的理念溯源快乐学习在教育实践中的体现 2.学习的快乐:内涵与价值学习的快乐的多维内涵学习的快乐对个人成长的价值 3.快乐的学习与学习的快乐的相互关系快乐的学习是学习快乐的重要前提学习的快乐是…...
Git 命令
参考文献: Git 教程 | 菜鸟教程Git 使用教程:最详细、最正宗手把手教学(万字长文)git忽略某个目录或文件不上传 文章目录 工作原理基本命令配置使用 其他命令日志分支回退标签 忽略指定文件远程仓库 工作原理 Git 是由 Linus To…...
365打卡第R6周: LSTM实现糖尿病探索与预测
🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 🏡 我的环境: 语言环境:Python3.10 编译器:Jupyter Lab 深度学习环境:torch2.5.1 torchvision0…...
新能源实验室电磁兼容设计优化方案论述
摘要:本文旨在进行新能源核心部件/系统测试实验室电磁兼容情况设计及优化方案进行论述,通过系统化梳理实验室的主流设备仪器,试验搭建典型方案。识别不同设备的电磁兼容现状,实验室基于设备布局常见设计方案不足点,故障…...
计算机图形学中的深度学习
文章目录 零、前言0.课程考核1.课程大纲2.前置知识3.教材4.课程大纲5.相关课程 Relevant Courses 一、计算机图形学1.本章学习目标2.图形学的应用3.SIG Graph papers 二、基本图形生成算法1.本章学习目标2.图形API3.OpenGL(1)什么是OpenGL(2)OpenGL 的基本组件:顶点…...
RockyLinux9.3-24小时制
在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制 案例一:在 RockyLinux 9.3 中,默认时间格式为 12 小时制,调整为 24 小时制案例二:时间显示英文调整为中文endl 案例一:在 Roc…...
25.2linux中外置RTC芯片的PCF8563实验(测试)_csdn
1、硬件原理图分析 知道了这些引脚我们还是按照老习惯! 配置镜像和设备树文件! 2、修改设备树 2.1、添加或者查找 PCF8563 所使用的 IO 的 pinmux 配置 打开stm32mp15-pincrtl.dtsi 文件,查找节点I2C4: 也就是中断引脚并不需要配置pinctrl…...
高性能 WEB 服务器 Nginx:多虚拟主机实现!
Nginx 配置多虚拟主机实现 多虚拟主机是指在一台 Nginx 服务器上配置多个网站 在 Nginx 中,多虚拟主机有三种实现方式: 基于IP地址实现多虚拟主机 基于端口号实现多虚拟主机 基于域名实现多虚拟主机 1 基于域名实现多虚拟主机 在 Nginx 中配置多个…...
C++ 的类型排序
0.前言 在 C 中,我编写了一个 tuple-like 模板,这个模板能容纳任意多且可重复的类型: template<typename... Ts> struct TypeList {};// usage: using List1 TypeList<int, double, char, double>; using List2 TypeList<…...
[计算机网络]拓扑结构
拓扑结构一般会在计网教材或课程的第一章计网的分类那里接触到,但实际上计网的拓扑结构并不只是第一章提到的总线型、星型、树型、网状、混合型那几种类型那么简单,学完了后面的数链层以后对拓扑结构会有新的体会,所以特别单独总结成一篇博客…...
C#方法返回值全解析:从基础语法到实战技巧
摘要:方法返回值是C#编程的核心概念之一。本文将带你彻底掌握返回值声明、void方法特性,以及如何通过返回值实现优雅的流程控制(文末附完整示例代码)。 返回值的基础法则 类型声明原则 有返回值:必须在方法名前声明…...
修复笔记:SkyReels-V2 项目中的 torch.cuda.amp.autocast 警告和错误
#工作记录 一、问题描述 在运行项目时,出现以下警告和错误: FutureWarning: torch.cuda.amp.autocast(args...) is deprecated. Please use torch.amp.autocast(cuda, args...) instead.with torch.cuda.amp.autocast(dtypepipe.transformer.dtype), …...
【TF-BERT】基于张量的融合BERT多模态情感分析
不足:1. 传统跨模态transformer只能处理2种模态,所以现有方法需要分阶段融合3模态,引发信息丢失。2. 直接拼接多模态特征到BERT中,缺乏动态互补机制,无法有效整合非文本模态信息 改进方法:1. 基于张量的跨模…...
SONiC-OTN代码详解(具体内容待续)
SONiC-OTN代码详解 (具体内容待续) 基于AI的源代码解析工具的产生使得代码阅读和解析变得越来越高效和简洁,计划通过这样的工具对SONiC在OTN领域的应用做一个全自动的解析,大部分内容会基于AI工具的自动解析结果。这样做的目的是…...
牛客周赛90 C题- Tk的构造数组 题解
原题链接 https://ac.nowcoder.com/acm/contest/107500/C 题目描述 解题思路 数组a是不可以动的,所以我们可以把a[i]*b[i]*i分成两组,分别为a[i]*i以及b[i] 然后策略就很明显了,让更大的b[i]匹配更大的a[i]*i 详细实现见代码。 代码&am…...
[ML]通过50个Python案例了解深度学习和神经网络
通过50个Python案例了解深度学习和神经网络 摘要:机器学习 (Machine Learning, ML)、深度学习 (Deep Learning, DL) 和神经网络 (Neural Networks, NN) 是人工智能领域的核心技术。Python 是学习和实践这些技术的首选语言,因为它提供了丰富的库(如 scikit-learn、Te…...
vue3 - keepAlive缓存组件
在Vue 3中,<keep-alive>组件用于缓存动态组件或路由组件的状态,避免重复渲染,提升性能。 我们新建两个组件,在每一个组件里面写一个input,在默认情况下当组件切换的时候,数据会被清空,但…...
自由学习记录(58)
Why you were able to complete the SpringBoot MyBatisPlus task smoothly: Clear logic flow: Database → Entity → Service → Controller → API → JSON response. Errors are explicit, results are verifiable — you know what’s broken and what’s fixed. Sta…...
短信侠 - 自建手机短信转发到电脑上并无感识别复制验证码,和找手机输验证码说再见!
自建手机短信转发到电脑上并无感识别复制验证码 一、前言 项目开发语言:本项目使用PythonRedisC#开发 你是否也遇到过这样的场景: 正在电脑上操作某个网站,需要输入短信验证码手机不在身边,或者在打字时来回切换设备很麻烦验证码…...
课程10. 聚类问题
课程10. 聚类问题 聚类此类表述的难点K 均值法让我们推广到几个集群的情况如果我们选择其他起始近似值会怎样? 结论在 sklearn 中的实现 如何处理已发现的问题?层次聚类Lance-Williams 算法Lance-Williams 公式在Scipy中实现 示例DBSCANDBSCAN 算法 聚类…...
深度学习中的数据增强:提升食物图像分类模型性能的关键策略
深度学习中的数据增强:提升食物图像分类模型性能的关键策略 在深度学习领域,数据是模型训练的基石,数据的数量和质量直接影响着模型的性能表现。然而,在实际项目中,获取大量高质量的数据往往面临诸多困难,…...
QT设计权限管理系统
Qt能够简单实现系统的权限设计 首先我们需要一个登陆界面 例如这样 然后一级权限,可以看到所有的内容,不设置菜单栏的隐藏。 然后其他权限,根据登陆者的身份进行菜单栏不同的展示。 菜单栏的隐藏代码如下: ui->actionuser-…...
从上帝视角看文件操作
1.为什么使用文件? 如果没有文件,我们写的程序中的数据是存储在电脑的内存中,当程序退出时,内存被回收后,数据就丢失了,等下次运行程序,是无法看到上次程序的数据的。(比如我们在程序中写通讯录时,联系人的相关数据都是放在内存中的,当程序退出时,这些数据也会随之消…...
【51单片机6位数码管显示时间与秒表】2022-5-8
缘由数码管 keil proteus 为什么出现这种情况呢?-编程语言-CSDN问答 #include "reg52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0,64}; //共阴0~F消隐减号 unsigned char cod…...
从头训练小模型: 4 lora 微调
1. LoRA (Low-Rank Adaptation) LoRA是一种高效的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)方法,原理是通过低秩分解的方式对预训练模型进行微调。 相比于全参数微调(Full Fine-Tuning),LoRA…...
前端开发,文件在镜像服务器上不存在问题:Downloading binary from...Cannot download...
问题与处理策略 问题描述 在 Vue 项目中,执行 npm i 下载依赖时,报如下错误 Downloading binary from https://npm.taobao.org/mirrors/node-sass//v4.14.1/win32-x64-72_binding.node Cannot download "https://npm.taobao.org/mirrors/node-sa…...
Debezium Binlog协议与事件转换详解
Debezium Binlog协议与事件转换详解 1. MySQL Binlog通信机制 1.1 连接建立流程 #mermaid-svg-eE88YFqcTG9kUWaZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eE88YFqcTG9kUWaZ .error-icon{fill:#552222;}#mer…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.1 日期时间标准化(时区转换/格式统一)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL数据分析实战:数据清洗之日期时间标准化(时区转换/格式统一)4.1 日期时间标准化:从混乱到有序4.1.1 数据乱象&…...
基于Hive + Spark离线数仓大数据实战项目(视频+课件+代码+资料+笔记)
精品推荐:基于Hive Spark离线数仓大数据实战项目,共23节课,供学习参考。 项目介绍项目中 docker 使用项目环境搭建项目数仓分层项目业务分析sqoop 数据采集python 数据采集项目 ODS 层创建DWD 层构建DWS 层构建项目回顾(一&…...
【深入浅出MySQL】之数据类型介绍
【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT(M)类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …...
从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地
Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地 本章聚焦 ESP32-S3 平台上如何利用 LSM6DS3 IMU 实现 死算(Dead Reckoning),并结合 零速更新(ZUPT) 或 磁力计辅助 进行 漂移校正,最终通过 EKF/UKF 融合提升定位精度。 一、传感器简介与校准 LSM6DS3 主要参数 加速…...
【iOS】 方法交换
【iOS】 方法交换 method-swizzling 文章目录 【iOS】 方法交换 method-swizzling前言什么是method-swizzling相关API方法交换的风险在load方法中保证只加载一次要在当前类的方法中进行交换如果方法依赖于cmd 方法交换的应用 前言 之前看过有关于消息转发的内容,这里我们可以简…...
PostgreSQL 的 ANALYZE 命令
PostgreSQL 的 ANALYZE 命令 ANALYZE 是 PostgreSQL 中用于收集数据库对象统计信息的关键命令,这些统计信息对于查询优化器生成高效执行计划至关重要。 一 ANALYZE 命令 1.1 基本语法 ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ] ANALYZE [ …...
初识 iOS 开发中的证书固定
引言 在移动应用安全领域,HTTPS/TLS 是数据传输的第一道防线,但仅依赖系统默认的证书验证仍有被中间人(MITM)攻击的风险。Certificate Pinning(证书固定)通过将客户端信任“钉”在指定的服务器证书或公钥上…...
2025 年如何使用 Pycharm、Vscode 进行树莓派 Respberry Pi Pico 编程开发详细教程(更新中)
micropython 概述 micropython 官方网站:https://www.micropython.org/ 安装 Micropython 支持固件 树莓派 Pico 安装 Micropython 支持固件 下载地址:https://www.raspberrypi.com/documentation/microcontrollers/ 选择 MicroPython 下载 RPI_PIC…...
设计模式每日硬核训练 Day 17:中介者模式(Mediator Pattern)完整讲解与实战应用
🔄 回顾 Day 16:责任链模式小结 在 Day 16 中,我们学习了责任链模式(Chain of Responsibility Pattern): 将请求沿链传递,节点可选择处理或传递下一节点。实现了请求发送者与多个处理者的解耦…...
文章记单词 | 第63篇(六级)
一,单词释义 vegetable [ˈvedʒtəbl] n. 蔬菜;植物人;生活单调乏味的人;adj. 蔬菜的;植物的faint [feɪnt] adj. 模糊的;微弱的;虚弱的;v. 昏倒,昏厥;n. 昏…...
ES类的索引轮换
通过以下请求方法创建一个名为 “tiered-storage-policy” 的 ISM policy: PUT _plugins/_ism/policies/tiered-storage-policy {"policy": {"description": "Changes replica count and deletes.","schema_version": 1,…...
小白机器人假想:分布式关节控制——机器人运动的未来模式?
引言 在机器人技术快速发展的今天,控制架构的创新往往能带来突破性进展。作为一名机器人爱好者,我最近思考了一个大胆的设想:如果机器人的每个关节都配备独立的动作存储器和处理器,并通过高速光纤网络与中央"驱动总脑"…...
LangChain4j +DeepSeek大模型应用开发——9 优化硅谷小鹿
1.预约业务的实现 这部分我们实现硅谷小鹿的查询订单、预约订单、取消订单的功能 创建MySQL数据库表 CREATE DATABASE xiaolu; USE xiaolu; -- 创建预约表 appointment CREATE TABLE appointment (id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键ID,自增, -- 主…...
Oracle VirtualBox 在 macOS 上的详细安装步骤
Oracle VirtualBox 在 macOS 上的详细安装步骤 一、准备工作1. 系统要求2. 下载安装包二、安装 VirtualBox1. 挂载安装镜像2. 运行安装程序3. 处理安全限制(仅限首次安装)三、安装扩展包(增强功能)四、配置第一个虚拟机1. 创建新虚拟机2. 分配内存3. 创建虚拟硬盘4. 加载系…...