FreeRTOS-rust食用指南
Rust 环境安装
rustup 是 Rust 的安装程序,也是它的版本管理程序,Linux 命令行下使用如下方式安装
# 安装 rustup
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
#更新 rustup
rustup update# 版本检查
rustc -V
cargo -V
FreeRTOS-rust 框架介绍
FreeRTOS-rust 是一个开源项目,旨在简化在嵌入式应用中使用 Rust 语言与 FreeRTOS 实时操作系统(RTOS)的集成。该项目基于 FreeRTOS 的原始 C 代码,并提供了 Rust 语言的接口。方便用户在嵌入式设备上使用 FreeRTOS 操作系统并使用 Rust 语言开发程序。
目录介绍
FreeRTOS-rust
├── .cargo # 对 cargo 本身的配置
│ └── config.toml
├── Cargo.toml # 对当前工作空间的配置
├── freertos-cargo-build # 负责对 freertos 源码进行编译
│ ├── Cargo.toml # 对当前 package 进行配置
│ └── src
│ └── lib.rs
├── freertos-rust # 负责编译 freertos 的 rust 接口层
│ ├── Cargo.toml # 对当前 package 进行配置
│ ├── build.rs # package 编译前自动调用的脚本
│ └── src # 适配层源码
│ ├── allocator.rs
│ ├── base.rs
│ ├── critical.rs
│ ├── delays.rs
│ ├── event_group.rs
│ ├── freertos # freertos C 接口适配层和实现的钩子函数
│ │ ├── ports
│ │ │ └── arm
│ │ │ └── hooks.c
│ │ └── shim.c
│ ├── hooks.rs
│ ├── isr.rs
│ ├── lib.rs
│ ├── mutex.rs
│ ├── patterns
│ │ ├── compute_task.rs
│ │ ├── mod.rs
│ │ ├── processor.rs
│ │ └── pub_sub.rs
│ ├── portmacro.h
│ ├── prelude
│ │ ├── mod.rs
│ │ └── no_std.rs
│ ├── queue.rs
│ ├── semaphore.rs
│ ├── shim.rs
│ ├── task.rs
│ ├── timers.rs
│ ├── units.rs
│ └── utils.rs
├── freertos-rust-examples # freertos 应用示例
│ ├── Cargo.toml # 对当前 package 进行配置
│ ├── FreeRTOS-Kernel # freertos 内核C源码
| ├── freertos-addons # freertos 扩展库C++源码(无需关注)
│ ├── build.rs # package 编译前自动调用的脚本
│ └── examples # 各平台的rust freertos 应用开发示例
│ ├── linux
│ ├── nrf9160
│ ├── stm32-cortex-m3
│ │ ├── FreeRTOSConfig.h
│ │ ├── layout.ld
│ │ ├── main.rs
│ │ └── memory.x
│ ├── stm32-cortex-m4-blackpill
│ └── win
└── publish-all.sh
框架介绍
FreeRTOS-rust 的整体框架分为三大块 freertos-cargo-build、freertos-rust、freertos-rust-examples,其中 freertos-cargo-build 负责对项目中所有 C语言代码的编译,包括 FreeRTOS-Kernel 内核源码,freertos C 适配层接口以及 freertos 各种钩子函数实现,内部利用 cc crate 以及 build.rs 文件中提供的信息,将C语言代码打包为静态库。freertos-rust 中包括了 freertos 的C适配层接口和钩子函数实现,以及转换为 rust 语言的对外接口,应用开发使用的 rust freertos 接口均来自这里。freertos-rust-examples 中包括了 freertos 的C语言内核源码以及各平台的rust 应用示例。
各部分使用的语言:
- FreeRTOS 内核源码:C 语言
- FreeRTOS 对外接口:Rust 语言
- APP 应用开发:Rust 语言
- 项目编译体系:Rust 语言
FreeRTOS-rust 项目集成
注:本次项目集成是以 STM32F103ZET6 芯片平台为基础进行的,其他芯片平台实现方式类似。
项目获取
github 开源代码仓库:https://github.com/lobaro/FreeRTOS-rust
git clone https://github.com/lobaro/FreeRTOS-rust.git
环境准备
Rust 工具链安装
设置使用 nightly 版本的 rust 工具链,能够使用更多的新功能。
# 将默认的 Rust 工具链设置为 Nightly 版本
rustup default nightly
# 安装 Nightly gun 工具链
rustup toolchain install nightly-gnu# 将 nightly-gnu 设置为默认工具链
rustup default nightly-gnu
添加新的目标平台
为工具链添加新的目标平台,添加平台后就可以使用 cargo build --target thumbv7m-none-eabi 编译进行指定平台的交叉编译了。
# 为工具链添加目标平台
rustup target add thumbv7m-none-eabi
调试工具安装
安装 cargo 和 llvm 工具用于对交叉编译生成的文件进行转换和分析,例如 cargo strip、cargo objdump 等。
cargo install cargo-binutils
rustup component add llvm-tools-preview
FreeRTOS 内核源码获取
项目在构件时会对 FreeRTOS 的源码进行交叉编译所以需要在项目根目录执行如下命令,拉取源码。
git submodule update --init --recursive
移植适配
examples Cargo.toml 配置修改
目录:./FreeRTOS-rust/freertos-rust-examples/Cargo.toml
将 stm32l1xx 的依赖库修改为 stm32f1xx 的依赖库,并将依赖库改为最新的库版本。
[package]
name = "freertos-rust-examples"
version = "0.1.1"
authors = ["Tobias Kaupat <tk@lobaro.de>"]
edition = "2018"
description = """
Create to use FreeRTOS in rust projects. It contains binaries for demos on some architecutres.
"""
keywords = ["FreeRTOS", "embedded", "demo", "examples"]
repository = "https://github.com/lobaro/FreeRTOS-rust"[dependencies]
freertos-rust = {path = "../freertos-rust"}[target.'cfg(target_arch = "arm")'.dependencies]
cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7.3"# Example: stm32-cortex-m3, [target.<triple>.dependencies] triple form cargo build --target thumbv7m-none-eabi
# or form .cargo/config.toml [build] target = "thumbv7m-none-eabi"
[target.thumbv7m-none-eabi.dependencies]
nb = "0.1.2"
embedded-hal = "0.2.3"
panic-halt = "0.2.0"
stm32f1xx-hal = {version = "0.10.0", features = ["rt", "stm32f103"], default-features = false}# Example: stm32-cortex-m4-blackpill
[target.thumbv7em-none-eabihf.dependencies]
panic-halt = "0.2.0"
embedded-hal = "0.2.3"
stm32f4xx-hal = {version = "0.8.3", features = ["rt", "stm32f411"]}# Example: nrf9160
[target."thumbv8m.main-none-eabihf".dependencies]
nrf9160-pac = "0.2.1"# Example: win
[target.x86_64-pc-windows-gnu.dependencies]# Example: linux
[target.x86_64-unknown-linux-gnu.dependencies][build-dependencies]
freertos-cargo-build = {path = "../freertos-cargo-build"}
stm32-cortex-m3 FreeRTOS配置修改
目录:
./FreeRTOS-rust/freertos-rust-examples/examples/stm32-cortex-m3/FreeRTOSConfig.h
// 修改CPU主频
// #define configCPU_CLOCK_HZ ( 4200000UL ) //also systick runs at this frequency
#define configCPU_CLOCK_HZ ( 72000000UL ) //also systick runs at this frequency// 禁止可视化跟踪调试
// #define configUSE_TRACE_FACILITY 1
#define configUSE_TRACE_FACILITY 0// 禁止堆栈溢出检测功能
// #define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_FOR_STACK_OVERFLOW 0// 禁用状态格式函数
// #define configUSE_STATS_FORMATTING_FUNCTIONS (1)
#define configUSE_STATS_FORMATTING_FUNCTIONS (0)
stm32-cortex-m3 连接脚本修改
目录:
./FreeRTOS-rust/freertos-rust-examples/examples/stm32-cortex-m3/layout.ld
./FreeRTOS-rust/freertos-rust-examples/examples/stm32-cortex-m3/memory.x
MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512KRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}
stm32-cortex-m3 main.rs 应用修改
目录:
./FreeRTOS-rust/freertos-rust-examples/examples/stm32-cortex-m3/main.rs
#![no_std]
#![no_main]
// For allocator
// #![feature(lang_items)]
#![feature(alloc_error_handler)]
use core::fmt::Write;
use core::panic::PanicInfo;
use core::alloc::Layout;use nb::block;use cortex_m;
use cortex_m::asm;
use cortex_m_rt::exception;
use cortex_m_rt::{entry, ExceptionFrame};use embedded_hal::digital::v2::OutputPin;
use freertos_rust::*;// use stm32f1xx_hal::gpio::*;
use stm32f1xx_hal::gpio::IOPinSpeed;
use stm32f1xx_hal::gpio::OutputSpeed;
use stm32f1xx_hal::timer::Timer;
use stm32f1xx_hal::serial;
use stm32f1xx_hal::rcc::RccExt;
use stm32f1xx_hal::time::U32Ext;
use stm32f1xx_hal::prelude::_fugit_RateExtU32;
use stm32f1xx_hal::prelude::_stm32_hal_afio_AfioExt;
use stm32f1xx_hal::prelude::_stm32_hal_flash_FlashExt;
use stm32f1xx_hal::prelude::_stm32_hal_gpio_GpioExt;use stm32f1xx_hal as hal;use crate::hal:: {stm32::{Peripherals},
};// extern crate panic_halt; // panic handler#[global_allocator]
static GLOBAL: FreeRtosAllocator = FreeRtosAllocator;fn delay() {let mut _i = 0;for _ in 0..2_00 {_i += 1;}
}fn delay_n(n: i32) {for _ in 0..n {delay();}
}pub struct MyDevice<D1: OutputPin> {d1: D1,
}impl<D1: OutputPin> MyDevice<D1>{pub fn from_pins(d1: D1) -> MyDevice<D1> {MyDevice {d1}}pub fn set_led(&mut self, on:bool){if on {let _ =self.d1.set_high();} else {let _ =self.d1.set_low();}}}#[entry]
fn main() -> ! {// 获取对内核外设的访问权限let cp = cortex_m::Peripherals::take().unwrap();// 获取对特定设备外设的访问权限let dp = Peripherals::take().unwrap();let mut afio = dp.AFIO.constrain();// 获得原始flash和rcc设备的所有权,并将它们转换为相应的HAL结构let mut flash = dp.FLASH.constrain();let rcc = dp.RCC.constrain();// 冻结系统中所有时钟的配置,并将冻结的频率存储在时钟树中let clocks = rcc.cfgr.freeze(&mut flash.acr);// 通过拆分 GPIOB 引脚,获取对其各引脚的互斥访问let mut gpiob = dp.GPIOB.split();let mut device = MyDevice::from_pins(gpiob.pb5.into_push_pull_output(&mut gpiob.crl));device.d1.set_speed(&mut gpiob.crl, IOPinSpeed::Mhz50);let mut gpioa = dp.GPIOA.split();// USART1 on Pins A9 and A10let pin_tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh);let pin_rx = gpioa.pa10;// 设置串口USART1的参数let serial = serial::Serial::new(dp.USART1,(pin_tx, pin_rx),&mut afio.mapr,serial::Config::default().baudrate(115200_u32.bps()).stopbits(serial::StopBits::STOP1).wordlength_8bits().parity_none(),&clocks,);// 将串行结构拆分为接收和发送部分let (mut tx, mut _rx) = serial.split();let number = 103;writeln!(tx,"Hello formatted string {}", number).unwrap();// 将系统计时器配置为每秒触发一次更新let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz();// 设置定时器的频率1Hztimer.start(1.Hz()).unwrap();// 等待计时器触发更新并更改LED的状态, 每秒钟切换 LED 状态(高电平/低电平)。for _i in 0..3 {// 等待定时器block!(timer.wait()).unwrap();// 设置高电平device.set_led(true);block!(timer.wait()).unwrap();// 设置低电平device.set_led(false);}device.set_led(false);// 创建任务Task::new().name("hello").stack_size(128).priority(TaskPriority(2)).start(move |_| {loop {freertos_rust::CurrentTask::delay(Duration::ms(100));tx.bwrite_all(b"led hight").unwrap();device.set_led(true);freertos_rust::CurrentTask::delay(Duration::ms(100));tx.bwrite_all(b"led low").unwrap();device.set_led(false);}}).unwrap();// 启动系统任务调度Task::new().name("hello").stack_size(128).priority(TaskPriority(2)).start(task_function).unwrap();FreeRtosUtils::start_scheduler();
}#[exception]
unsafe fn DefaultHandler(_irqn: i16) {
// custom default handler
// irqn is negative for Cortex-M exceptions
// irqn is positive for device specific (line IRQ)
// set_led(true);(true);
// panic!("Exception: {}", irqn);
}#[exception]
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {loop {// 在这里添加遇到 HardFault 时希望执行的代码}
}// define what happens in an Out Of Memory (OOM) condition
#[alloc_error_handler]
fn alloc_error(_layout: Layout) -> ! {asm::bkpt();loop {// 在这里添加遇到 error 时希望执行的代码}
}#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {loop {// 在这里添加遇到 panic 时希望执行的代码}
}
编译烧录
项目编译
在项目根目录下执行如下指令进行进行编译并转换为 Hex 文件用于烧录
# 编译整个项目
cargo build --package freertos-rust-examples --example stm32-cortex-m3 --target thumbv7m-none-eabi --release
# 删除ELF执行文件中的符号表
cargo strip --target thumbv7m-none-eabi --example stm32-cortex-m3 --release
# ELF文件转Hex文件用于stm32f103烧录
cargo objcopy --example stm32-cortex-m3 --target thumbv7m-none-eabi -- -O ihex stm32-cortex-m3.hex
固件烧录
从 Linux 环境拷贝出 stm32-cortex-m3.hex 文件到 window 环境,然后使用 Keil、STM32 ST-LINK Utility 等方式进行烧录即可,具体方法请自行百度。
总结:
FreeRTOS-rust 项目基于 FreeRTOS 内核源码构建安全的 rust 应用开发环境,要比一些使用纯 rust 重新开发 FreeRTOS 的项目更加贴合实际,对比的优点主要有以下部分:
- 使用 C语言的 FreeRTOS 内核源码要比使用 rust 重新开发的内核源码至少在体积上小 3倍左右。
- 使用 C语言的 FreeRTOS 内核源码稳定性更好,因为开源版本已经经过了无数轮的迭代和问题修复。
- 使用 C语言的 FreeRTOS 内核源码这种方式目前在实际项目应用中更具有可行性,因为大部分嵌入式项目的底座还是 C的。
但是在获取 rust 内存安全特性的同时也会带来一些问题: - 应用层使用 rust 开发,FreeRTOS 内核源码依然是C语言的,这部分代码 rust 的安全机制无法进行追踪,如果出现问题,更加难以排查。
- 目前在嵌入式领域很多优秀的开源 C 语言组件还没有实现 rust 重写,应用层如果想完全使用 rust 开发,目前还存在一些难度,当然 rust 项目也可以使用之前的 C库组件。
- 使用 rust 开发应用程序不可避免的需要进行外设操作甚至是MCU的寄存器操作,目前嵌入式芯片的底层 rust 驱动库不够多,很多芯片没有 rust 的底层驱动库,类似与 stm32 的 ARM 系列芯片虽然已经有底层驱动库,但是版本还在迭代,使用起来不是特别方便。
- 使用 rust 进行应用层开发,代码的体积是需要首先考虑的事情,一般来说,同样功能的实现,rust 代码体积至少比 C代码体积大2~3倍。
🌀路西法 的个人博客拥有更多美文等你来读。
相关文章:
FreeRTOS-rust食用指南
Rust 环境安装 rustup 是 Rust 的安装程序,也是它的版本管理程序,Linux 命令行下使用如下方式安装 # 安装 rustup curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh #更新 rustup rustup update# 版本检查 rustc -V cargo -VFreeRTOS-rust…...
如何使用智能化RFID管控系统,对涉密物品进行安全有效的管理?
载体主要包括纸质文件、笔记本电脑、优盘、光盘、移动硬盘、打印机、复印机、录音设备等,载体(特别是涉密载体)是各保密、机要单位保证涉密信息安全、防止涉密信息泄露的重要信息载体。载体管控系统主要采用RFID射频识别及物联网技术…...
0基础学LabVIEW
对于零基础的朋友来说,学习LabVIEW需要一个科学的学习路径和方法。通过观看优质的B站教程打好基础,再结合实际项目进行实践操作,能够快速提升LabVIEW的应用能力。以下是从入门到进阶的学习建议。 一、利用B站入门教程打基础 筛选优质教程…...
Go语言精进之路读书笔记(第二部分-项目结构、代码风格与标识符命名)
说明:《Go语言精进之路》第一部分-熟知Go语言的一切,不在博客中做读书笔记了,大家可以自己读一读,每个人心里都会有自己对Go语言的认识和理解。 直接从第二部分-项目接口、代码风格与标识符命名开始 第二章目录如下 第5条 使用…...
Windows server 2016 无法部署docker问题
根据流程winserver16安装docker ee,发现服务器管理器的添加角色和功能-功能中没有 container 根据流程winserver16安装docker desktop,发现安装 hyper-v 报错 原因: 本人测试用windows server 2016使用vmware搭建,而vmware本身可…...
智能AI之隐私安全,尤其是医疗
前言 智能AI能更好的服务我们的生活,各行各业都将会有她的影子。我们在依赖她的情况下,我们的隐私安全吗? 前两天分享了用她分析CT拍片、还有一份血检报告单,回复的确实比有些医生都说的专业全面。以至于我都有冲动依赖她开…...
【hot100】054螺旋矩阵
一、思路 这个题目主要有两个问题,一是什么时候切换方向,二是如何切换方向 问题一:此步移动完后,判断下一个元素,如果大于等于边界值(从0开始)或者小于边界值时或者访问数组为真时 问题二&am…...
【Java学习】类和对象
目录 一、选择取块解 二、类变量 三、似复刻变量 四、类变量的指向对象 五、变量的解引用访问 1.new 类变量(参) 2.this(参) 3.类变量/似复刻变量. 六、代码块 七、复制变量的赋值顺序 八、访问限定符 1.private 2.default 九、导类 一、选择取块解 解引用都有可以…...
TestHubo基础教程-创建项目
TestHubo是一款国产开源一站式测试工具,涵盖功能测试、接口测试、性能测试,以及 Web 和 App 测试,可以满足不同类型项目的测试需求。本文将介绍如何快速创建第一个项目,以快速入门上手。 1、创建项目 在 TestHubo 中,…...
JS 链表
文章目录 链表题的一些总结两种链表定义set存储链表节点,存的是整个空间同时处理长短不一的两个链表处理方法 while(l1 || l2)处理方法 while(l1 & l2) dummyhead的使用 链表题的一些总结 两种链表定义 class class ListNode {val;next null;constructor(va…...
数据结构(陈越,何钦铭)第三讲 树(上)
3.1 树与数的表示 3.1.1 顺序查找 int SequentialSearch(List Tbl,ElementType K){int i;Tbl->Element[0]K;for(iTbl->Length;Tbl->Element[i]!K;i--);return i; } typedef struct LNode *List; struct LNode{ElementType Element[MAXSIZE];int Length; };3.1.2 二分…...
企业文件安全:零信任架构下的文件访问控制
在企业数字化转型的进程中,传统的文件访问控制模型已难以满足日益复杂的网络安全需求。零信任架构作为一种新兴的安全理念,为企业的文件安全访问提供了全新的解决方案。 一、传统文件访问控制的局限性 传统的文件访问控制主要基于网络边界,…...
性格测评小程序06用户注册校验
目录 1 必填校验2 验证密码强度3 账号唯一性校验最终效果总结 上一篇我们介绍了用户注册的功能,注册的时候对密码进行了加密。除了密码加密外还需要验证账号的唯一性和密码强度的问题,本篇我们介绍一下如何在表单提交的时候增加自定义校验的能力。 1 必填…...
$符(前端)
1. jQuery 的别名 用途:$ 是 jQuery 的核心标识符,用于快速选择 DOM 元素或调用 jQuery 方法。 // 选择所有 <div> 元素并隐藏 $(div).hide(); // 发起 AJAX 请求 $.get(/api/data, response > console.log(response)); 注意:虽然…...
Windows 11如何显示全部右键菜单?
在Windows 11系统中,默认的右键菜单进行了简化,若你想要显示全部右键菜单,可以通过以下几种方法实现: 方法一:临时显示完整右键菜单 在需要操作的区域按下Shift键的同时点击鼠标右键,此时弹出的就是完整的…...
离线量化算法和工具 --学习记录1
离线量化算法和工具 一、离线量化的基础概念1.1、基本流程1.2、量化的优点和缺点1.3、如何生产一个硬件能跑的量化模型1.4、PTQ的概念以及和QAT的区别1.5、离线量化的标准流程1.6、校准数据的选择1.7、量化模式的选择1.8、校准方式的选择1.9、量化算法的选择1.10、写入量化参数…...
python第七课
WSGI Middleware 中间件,可以理解称对应用程序的一组装饰器,对两边都起作用的元素。 重写environ,然后基于URL,将请求对象路由给不同的应用对象支持多个应用或者框架顺序地运行于同一个进程中通过转发请求和相应,支持负…...
华为IPD简介
创作灵感 现在“熟悉华为IPD”经常出现在高级招聘岗位能力要求上,于是作者写下此文章以此巩固相关知识储备 名词解释 华为IPD(Integrated Product Development,集成产品开发)是华为引入并优化的一套产品开发管理体系࿰…...
如何在Spring Boot中配置分布式配置中心
文章目录 如何在Spring Boot中配置分布式配置中心分布式配置中心的概念1. 集中管理2. 动态配置3. 环境隔离4. 安全性5. 可扩展性与适应性6. 与 CI/CD 流程的集成Spring Cloud Config 概述1. 集中式配置管理2. 多环境支持3. 版本控制4. 动态刷新5. 安全性6. 与微服务架构的无缝集…...
Golang internals
To be continued... time.Time golang的时区和神奇的time.Parse context.Context Go Context的踩坑经历 sync.Pool sync.Pool workflow in Go 1.12 new shared pools in Go 1.13 什么是cpu cache理解 Go 1.13 中 sync.Pool 的设计与实现Go: Understand the Design of Sync.Pool…...
DiscreteDeviceAssigner:让Hyper-V设备直通像点菜一样简单
DiscreteDeviceAssigner:让Hyper-V设备直通像点菜一样简单 【免费下载链接】DDA 实现Hyper-V离散设备分配功能的图形界面工具。A GUI Tool For Hyper-Vs Discrete Device Assignment(DDA). 项目地址: https://gitcode.com/gh_mirrors/dd/DDA 你是否曾经在Hy…...
大模型行业爆发式增长,程序员转型的最佳时机,现在上车还不晚
文章目录前言一、2026年大模型行业爆发式增长,风口已经来了1.1 市场规模爆炸式增长,企业需求井喷1.2 人才缺口巨大,薪资水涨船高1.3 技术门槛大幅降低,普通人也能上车二、程序员转型大模型,这4个方向性价比最高2.1 AI工…...
1.6T光模块将成AI数据中心主流
2026年光通信模组的发展核心驱动力来自AI算力集群对超高带宽和极致能效的迫切需求,其技术演进呈现出高速率、高集成、低功耗、新架构的鲜明特征。光互连技术正从传统可插拔形态向更紧密的共封装光学(CPO) 和线性驱动可插拔光学(LP…...
从零到一:基于腾讯IM与TRTC构建Android原生语音通话SDK的实战指南
1. 为什么选择腾讯IMTRTC组合? 在Android端实现语音通话功能时,你可能遇到过这样的困境:自己从头开发WebRTC方案要处理复杂的编解码和网络适配,用第三方开源方案又担心稳定性和扩展性。我经历过三个失败的技术选型后,最…...
基于XGBoost与神经网络的NBA赛果预测:从数据采集到凯利公式下注
1. 项目概述:用机器学习预测NBA赛果与盘口如果你对NBA比赛和数据分析都感兴趣,那么把两者结合起来,用机器学习模型来预测比赛胜负和总分盘口(大小分),无疑是一件极具吸引力的事情。这不仅仅是简单的数据堆砌…...
Go语言开发的MySQL binlog解析利器my2sql:除了闪回,它的统计功能更值得DBA关注
Go语言开发的MySQL binlog解析利器my2sql:统计功能如何重塑DBA工作流 当大多数DBA将my2sql视为又一款闪回工具时,它的统计模块正在悄然改变数据库性能分析的范式。这个用Go语言编写的高效工具,能在90秒内解析1.1GB的binlog文件,其…...
保姆级教程:用STM32+ESP8266+MQTT协议,5分钟搞定OneNet温湿度数据上传(附完整源码)
从零搭建物联网温湿度监测系统:STM32与ESP8266实战指南 在智能家居和工业物联网快速发展的今天,远程监测环境数据已成为刚需。本文将带你用最常见的STM32单片机和ESP8266 WiFi模块,配合MQTT协议,快速构建一个稳定可靠的温湿度上传…...
C++内存管理:new/delete与内存泄漏实战
一、上期回顾掌握函数模板、类模板、泛型编程、模板特化,理解了 STL 容器能适配任意类型的底层原因。今天攻坚C 内存管理,搞定 new/delete、内存分区、野指针、内存泄漏四大核心痛点。二、C/C 程序内存五大分区程序运行时内存划分为 5 块,面试…...
如何用douyin-downloader轻松保存抖音内容:从零开始的完整指南
如何用douyin-downloader轻松保存抖音内容:从零开始的完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallba…...
RAGxplorer:构建可观测RAG系统,实现数据驱动优化与调试
1. 项目概述:RAGxplorer,一个为RAG系统打造的“X光机” 如果你正在构建或优化一个基于检索增强生成(RAG)的系统,那么你一定遇到过这样的困惑:为什么用户的问题没有得到预期的答案?是检索的文档不…...
