FreeRTOS互斥信号量解决优先级翻转实战教程
FreeRTOS互斥信号量解决优先级翻转实战教程
大家好!今天我们来深入探讨FreeRTOS中的优先级翻转问题,并通过互斥信号量来解决这个问题。上一篇文章我们已经了解了优先级翻转的现象,今天我们将动手实践,通过代码对比来直观感受互斥信号量的作用。
🚀 本文是FreeRTOS学习系列的一部分。完整教程请访问我的GitHub仓库:https://github.com/Despacito0o/FreeRTOS,从入门到精通的全面指南!
一、互斥信号量解决优先级翻转
了解完互斥信号量可以解决优先级翻转的问题,我们来实际体验一下。我们将使用前面优先级翻转的案例,把它改造成使用互斥信号量的版本,然后观察效果。
首先,我们直接拷贝之前的012工程,重命名为013:
二、从二值信号量切换到互斥信号量
我们有三个任务,三个任务的逻辑不需要修改,只需要将创建的信号量类型从二值信号量换成互斥信号量。
要使用互斥信号量,必须先在FreeRTOSConfig.h中开启相关配置:
#define configUSE_MUTEXES 1 // 是否启用互斥信号量
三、创建互斥信号量
接下来,我们将二值信号量的创建函数替换为互斥信号量的创建函数:
xSemaphoreCreateMutex();
让我们深入看看这个函数的实现:
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_MUTEXES == 1 ) )#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#endif
进一步查看xQueueCreateMutex
函数的实现:
#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ){QueueHandle_t xNewQueue;const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );prvInitialiseMutex( ( Queue_t * ) xNewQueue );return xNewQueue;}#endif /* configUSE_MUTEXES */
最后看看prvInitialiseMutex
函数:
static void prvInitialiseMutex( Queue_t * pxNewQueue )
{if( pxNewQueue != NULL ){/* 队列创建函数会为通用队列正确设置所有队列结构成员,* 但这个函数是创建互斥量。覆盖那些需要不同设置的成员 - * 特别是优先级继承所需的信息。 */pxNewQueue->u.xSemaphore.xMutexHolder = NULL;pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;/* 为递归互斥量做准备 */pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0;traceCREATE_MUTEX( pxNewQueue );/* 以预期状态开始信号量 */( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );}else{traceCREATE_MUTEX_FAILED();}
}
可以看到,创建完互斥信号量后,会自动调用一次xQueueGenericSend
,相当于主动释放了一次资源,这与我们之前介绍的"互斥信号量默认创建完会自动释放一次资源"一致。
因此,我们只需要简单地替换创建函数即可:
myPrintfQueueHandler = xSemaphoreCreateMutex(); // 创建互斥信号量,创建成功会自动释放一次信号量
四、编译调试,观察现象
我们编译、调试、运行代码:
现在,我们通过串口输出分析互斥信号量的效果。
在没有使用互斥信号量的情况下,当高优先级任务3尝试获取已被低优先级任务1占用的信号量时,任务3会阻塞;此时中优先级任务2可以抢占任务1执行,导致任务1无法快速释放信号量,任务3长时间等待,出现优先级翻转。
而使用互斥信号量后,我们可以看到:当任务3(高优先级)尝试获取被任务1(低优先级)持有的互斥信号量时,任务1的优先级会被临时提升到与任务3相同的级别,这样任务2(中优先级)就无法抢断任务1的执行了。
通过串口输出,我们可以发现:
- 任务1获取互斥信号量后开始执行
- 当任务3尝试获取同一个互斥信号量时,任务1的优先级被提升
- 此时任务2无法抢占任务1,任务1可以继续执行并最终释放互斥信号量
- 任务1释放互斥信号量后,其优先级被恢复为原来的值
- 任务3获取互斥信号量并执行
这就验证了互斥信号量通过优先级继承机制解决优先级翻转的工作原理。
五、代码分析
让我们详细分析一下任务执行的完整过程:
- 首先,高优先级的任务3先完整执行一轮,然后进入延时状态(vTaskDelay(1000))
- 接着,中优先级的任务2开始执行,它需要执行1.5秒
- 但在任务2执行1秒后,任务3的延时结束,抢占执行权,获取互斥信号量,执行自己的逻辑,然后释放互斥信号量并再次进入延时状态
- 任务2继续执行剩余的0.5秒,然后也进入延时状态
- 这时轮到低优先级的任务1执行,它获取互斥信号量并开始执行
- 0.5秒后,任务3的延时结束,尝试获取互斥信号量,但发现信号量被任务1占用
- 关键点:此时任务1的优先级被临时提升到与任务3相同的级别
- 由于任务1现在具有与任务3相同的高优先级,任务2无法抢断其执行
- 任务1可以继续执行直到释放互斥信号量
- 任务1释放互斥信号量后,其优先级恢复原值,任务3获取信号量并开始执行
- 任务3执行完毕后,再次轮到任务2执行,而不是任务1,这证明任务1的优先级已被恢复
这整个过程清晰地展示了互斥信号量如何通过优先级继承机制解决优先级翻转问题。
六、完整代码
下面是完整的示例代码,使用互斥信号量解决优先级翻转:
#include "stm32f10x.h" // Device header
#include "FreeRTOS.h"
#include "task.h"
#include "usart.h"
#include "semphr.h"
#include "delay.h"TaskHandle_t myTaskHandler1;
TaskHandle_t myTaskHandler2;
TaskHandle_t myTaskHandler3;
TaskHandle_t startTaskHandler;QueueHandle_t myPrintfQueueHandler;void myTask1(void *arg)
{BaseType_t res = 0;while (1){taskENTER_CRITICAL();/* 获取信号量 */printf("The low-priority Task1 gets the semaphore\r\n");res = xSemaphoreTake(myPrintfQueueHandler, portMAX_DELAY);if (res != pdPASS){printf("Task1 failed to get semaphore\r\n");}/* 执行其他逻辑 */printf("A low-priority Task1 is being executed\r\n");Delay_ms(3000);/* 释放信号量 */printf("Low-priority Task1 releases semaphores\r\n");res = xSemaphoreGive(myPrintfQueueHandler);if (res != pdPASS){printf("Task1 failed to release semaphore\r\n");}taskEXIT_CRITICAL();vTaskDelay(1000);}
}void myTask2(void *arg)
{while (1){taskENTER_CRITICAL();printf("Task 2 of medium priority is being executed\r\n");Delay_ms(1500);printf("task2 is executed once\r\n");taskEXIT_CRITICAL();vTaskDelay(1000);}
}void myTask3(void *arg)
{BaseType_t res = 0;while (1){taskENTER_CRITICAL();/* 获取信号量 */printf("The high priority Task3 gets the semaphore\r\n");res = xSemaphoreTake(myPrintfQueueHandler, portMAX_DELAY);if (res != pdPASS){printf("Task3 failed to get semaphore\r\n");}/* 执行其他逻辑 */printf("High Priority Task3 is executing...\r\n");Delay_ms(1000);/* 释放信号量 */printf("A high-priority Task3 releases a semaphore\r\n");res = xSemaphoreGive(myPrintfQueueHandler);if (res != pdPASS){printf("Failed to release semaphore in Task3\r\n");}taskEXIT_CRITICAL();vTaskDelay(1000);}
}void startTask(void *arg)
{taskENTER_CRITICAL();printf("startTask runnig\n");taskEXIT_CRITICAL();xTaskCreate(myTask1,"myTask1",128,NULL,2,&myTaskHandler1);xTaskCreate(myTask2,"myTask2",128,NULL,3,&myTaskHandler2); // 注意这里的优先级设置xTaskCreate(myTask3,"myTask3",128,NULL,4,&myTaskHandler3); // 任务名应为myTask3vTaskDelete(NULL);
}int main(void)
{USART_Config();myPrintfQueueHandler = xSemaphoreCreateMutex(); // 创建互斥信号量if(myPrintfQueueHandler == NULL){printf("The semaphore is created failed\r\n");}else {printf("The semaphore is created successfully\r\n");}xTaskCreate(startTask,"startTask",128,NULL,2,&startTaskHandler);vTaskStartScheduler();while (1){}
}StaticTask_t IdleTaskTCB;
StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize )
{* ppxIdleTaskTCBBuffer = &IdleTaskTCB;* ppxIdleTaskStackBuffer = IdleTaskStack;* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
注意:在startTask函数中,我修正了三个任务的优先级设置,分别为2、3、4,确保优先级递增,且修正了第三个任务的名称应为"myTask3"。
七、总结与拓展
通过本文的实践,我们清晰地看到了互斥信号量是如何通过优先级继承机制解决优先级翻转问题的。当高优先级任务等待低优先级任务持有的资源时,低优先级任务的优先级被临时提升,以防止中优先级任务抢占执行权。
互斥信号量与二值信号量的区别
- 优先级继承:互斥信号量支持优先级继承,二值信号量不支持
- 用途:互斥信号量专门用于互斥访问共享资源,二值信号量更适合任务同步
- 所有权:互斥信号量有所有权概念,只有获取者才能释放;二值信号量没有所有权概念
- 递归性:FreeRTOS还提供递归互斥信号量,允许同一任务多次获取同一互斥量
优先级继承的局限性
优先级继承机制虽然能解决优先级翻转问题,但仍有一些局限性:
- 只能解决单个互斥量的情况,对于多个互斥量形成的死锁,无能为力
- 增加了系统开销,尤其是频繁的优先级调整
- 在某些极端情况下可能导致系统行为不可预测
优先级天花板协议
除了优先级继承,还有一种解决优先级翻转的方法是"优先级天花板协议"(Priority Ceiling Protocol)。该协议为每个互斥信号量指定一个优先级天花板,任何获取该互斥量的任务都会临时提升到这个优先级。虽然FreeRTOS没有直接实现这一协议,但我们可以通过适当的设计来模拟它。
🔥 完整的FreeRTOS学习项目请访问:https://github.com/Despacito0o/FreeRTOS,从入门到精通的全面指南!
这个开源项目提供了从入门到精通的FreeRTOS学习资源,包括详细的移植教程、丰富的示例代码和深入浅出的文档说明,欢迎大家star和fork!
如果你对FreeRTOS有更多疑问或建议,欢迎在评论区留言,也欢迎关注我获取更多嵌入式开发内容!
相关文章:
FreeRTOS互斥信号量解决优先级翻转实战教程
FreeRTOS互斥信号量解决优先级翻转实战教程 大家好!今天我们来深入探讨FreeRTOS中的优先级翻转问题,并通过互斥信号量来解决这个问题。上一篇文章我们已经了解了优先级翻转的现象,今天我们将动手实践,通过代码对比来直观感受互斥…...
Spark-SQL 四(实验)
用idea实验hive的常用代码 将数据放到项目的目录下 代码实现 运行结果: 实验 统计有效数据条数及用户数量最多的前二十个地址 将数据放到Spark-SQL/input目录下 代码实现: 运行结果:...
前端技术未来的发展趋势分析
以下是关于前端技术未来发展趋势的深度分析,结合行业动态和技术演进方向,从多个维度展开: 一、核心发展趋势 1. 框架融合与性能极致化 趋势:React/Vue/Solid 等框架在编译时优化(如React Forget编译器)和…...
字节扣子空间开启内测!附免费邀请码!
3月初,当Manus作为首个通用智能体横空出世时,整个科技圈都沸腾了。 当时我就预言过:这种创新产品要真正普及,还得看大厂动作(毕竟创业公司的资源有限啊)。 这不,字节跳动最近就悄悄放出了大招—…...
高并发场景下的淘宝 API 开发实践:商品数据实时采集与性能优化
在电商行业竞争激烈的当下,实时获取海量商品数据成为企业把握市场动态、制定精准策略的关键。然而,高并发场景下对淘宝 API 的调用极易引发性能瓶颈与稳定性问题。本文将围绕高并发场景下淘宝 API 开发,深入讲解商品数据实时采集的技术要点&a…...
如何将Qt程序打包成应用程序?
1、使用release模式,编译项目 2、新建一个文件夹(不要有中文路径),将刚才编译生成的可执行文件(.exe)放入新建的文件夹下。 可执行文件通常生成在项目目录下的构建文件夹中,如 build-项目名-套…...
AI重塑网络安全:机遇与威胁并存的“双刃剑”时代
一、引言 人工智能(AI)技术的迅猛发展,正在深刻改变网络安全行业的格局。从ChatGPT生成钓鱼邮件到AI驱动的漏洞挖掘,从零信任架构的普及到安全大模型的实战应用,AI既是攻击者的“新武器”,也是防御者的“新…...
c++基础·列表初始化
目录 一、列表初始化的核心优势 二、基础数据类型与数组初始化 1. 基础类型初始化 2. 数组初始化 三、类与结构体初始化 1. 构造函数匹配规则 2. 注意事项 四、标准容器初始化 五、聚合类型(Aggregate Types)初始化 1. 聚合类型定义 2. 初始化…...
颠覆传统!毫秒级响应的跨平台文件同步革命,远程访问如本地操作般丝滑
文章目录 前言1. 安装Docker2. Go File使用演示3. 安装cpolar内网穿透4. 配置Go File公网地址5. 配置Go File固定公网地址 前言 在这个信息爆炸的时代,谁不曾遭遇过类似的窘境呢?试想,当你正于办公室中埋首案牍时,手机突然弹出一…...
目标检测中的损失函数(二) | BIoU RIoU α-IoU
BIoU来自发表在2018年CVPR上的文章:《Improving Object Localization With Fitness NMS and Bounded IoU Loss》 论文针对现有目标检测方法只关注“足够好”的定位,而非“最优”的框,提出了一种考虑定位质量的NMS策略和BIoU loss。 这里不赘…...
RS232 串行通信:C++ 实现指南
文章目录 一、RS232 简介1. 电气特性2. 传输速率3. 传输距离 二、在 C 中实现 RS232 通信1. Windows 平台(1)打开串行端口(2)配置串行通信参数(3)发送数据(4)接收数据(5&…...
电控---SWD协议
SWD协议是烧录调试常用的协议,本文对SWD协议进行了,覆盖物理层、协议层、寄存器结构、信号时序、安全特性、实际应用及最新发展趋势的讲解。 一、物理层架构与信号特性 1. 引脚定义与电气规范 核心引脚: SWDIO(双向数据线&…...
Linux系统下docker 安装 redis
docker安装最新版的redis 一、docker拉取最新版redis镜像 拉取镜像若没有指定版本,代表拉取最新版本 二、查询redis镜像 三、挂载配置文件 在docker容器内修改redis配置文件不方便,所以挂载配置文件,这样可以在外边修改redis配置 3.1 创建…...
第 2 篇:初探时间序列 - 可视化与基本概念
第 2 篇:初探时间序列 - 可视化与基本概念 (图片来源: Luke Chesser on Unsplash) 在上一篇《你好,时间序列!》中,我们了解了什么是时间序列数据以及学习它的重要性。现在,是时候卷起袖子,真正开始接触和探…...
适配器模式:化解接口不兼容的桥梁设计
适配器模式:化解接口不兼容的桥梁设计 一、模式核心:让不兼容的接口协同工作 在软件开发中,经常会遇到接口不兼容的情况:如旧系统提供的接口无法被新系统直接调用,或第三方库的接口与当前系统设计不匹配。适配器模式…...
科大讯飞Q1营收46.6亿同比增长27.7%,扣非净利同比增长48.3%
4月21日盘后,AI龙头科大讯飞(002230.SZ)发布2024年报,公司全年实现营业收入233.43亿元,同比增长18.79%,同期归母净利润为5.6亿元。 公司核心赛道业务保持快速增长,消费者、教育、汽车、医疗业务…...
基于大模型的血栓性外痔全流程风险预测与治疗管理研究报告
目录 一、引言 1.1 研究背景与目的 1.2 研究意义 二、血栓性外痔概述 2.1 定义与发病机制 2.2 临床表现与诊断方法 2.3 现有治疗手段综述 三、大模型在血栓性外痔预测中的应用原理 3.1 大模型技术简介 3.2 模型构建与训练数据来源 3.3 模型预测血栓性外痔的工作流程…...
Transformer系列(三):编码器—解码器架构
Transformer架构 一、多头自注意力 (Multi-head self-attention)将矩阵维度从d降到d/k的优点 二、层归一化 (Lary Norm)三、残差连接 (Residual Connections)Add and Norm 四、注意力对数几率缩放 (Attention logit scaling)五、T…...
C++入门小馆: 深入string类(二)
嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的pa…...
MCU开发学习记录10 - 高级定时器学习与实践(HAL库)—PWM互补输出、死区控制、刹车控制 - STM32CubeMX
本文将介绍高级定时器的概念(只讲解高级定时器特有功能)、相关函数以及STM32CubeMX生成定时器的配置函数以及对生成定时器的配置函数进行分析(包括结构体配置、相关寄存器配置)。针对于高级定时器实践:实现输出PWM互补…...
pytest基础-new
规范 1、首先创建 py 文件命名以 test_ 开始或者以 _test 结尾 2、若是新建类,测试类需要以 Test_开头 3、测试用例(方法)需要以 test_开头 assert 断言 assert xx:判断 xx 为真 assert not xx:判断 xx 不为真 asse…...
利用Qt创建一个模拟问答系统
界面: 添加了聊天显示区域(QTextEdit) 添加了发送按钮和清空对话按钮 优化了布局和窗口大小添加了时间戳显示 2、功能: 支持实时对话可以清空对话历史 支持按回车发送消息 添加了简单的关键词匹配响应系统 交互体验&#x…...
CCF CSP 第37次(2025.03)(1_数值积分_C++)
CCF CSP 第37次(2025.03)(1_数值积分_C) 解题思路:思路一: 代码实现代码实现(思路一): 时间限制: 1.0 秒 空间限制: 512 MiB 原题链接 解题思路…...
使用 Flutter 遇坑小计
前言 首先, 谷哥很贴心地为国内用户准备了一份使用手册 不过很遗憾 就算你照着它的手册来了, 还是会在后续使用中遇到其它的坑 今天我踩了, 保不齐明天就是其他人(lol) running gradle task ‘assembledebug’ stuck 首先去确定下当下Android Studio(或者说你目前的Flutter项…...
C语言中的双链表和单链表详细解释与实现
C语言中的双链表详细解释与实现 双链表(Doubly Linked List)是一种常见的数据结构,它比单链表更灵活,因为每个节点都包含指向前驱和后继节点的指针。 双链表的基本结构 节点定义 c 复制 下载 typedef struct Node {int dat…...
CSS零基础入门笔记:狂神版
前言 本笔记是学习狂神的java教程,建议配合视频,学习体验更佳。 【狂神说Java】HTML5完整教学通俗易懂_哔哩哔哩_bilibili 第1-2章:Java零基础入门笔记:(1-2)入门(简介、基础知识)-CSDN博客 第3章&…...
使用python调用deepseek 多轮对话,详细讲解
以下代码实现在python中与deepseek实现多轮对话。 Messages参数是对话历史和上下文的核心载体。 数据结构: • 必须是包含消息对象的数组 • 每个消息对象必须包含: o role:发言者身份(system/user/assistant) o con…...
requestAnimationFrame是什么?【前端】
亲爱的读者,希望今天的你好心情~ 目录 requestAnimationFrame是什么?目的?举个栗子: requestAnimationFrame是什么? requestAnimationFrame 是一种用于优化动画性能的 JavaScript API。它允许你在浏览器的下一次重绘之…...
SQL Server基础
二. SQL Server数据库 1. 数据库简介 数据库本质是写成磁盘文件,在硬盘中存储用处 存储大量数据,方便检索和访问保持数据信息的一致、完整共享和安全通过组合分析,产生新的有用信息 数据库发展史 萌芽阶段:文件系统,…...
Vue-组件的懒加载,按需加载
在Vue项目中实现组件的懒加载(也称为按需加载或代码分割),可以大大提升应用的加载速度和性能。懒加载主要通过Webpack的代码分割功能实现,特别是使用动态导入(import()语法)。 为什么要使用懒加载…...
Docker 镜像、容器和 Docker Compose的区别
前言:Docker 的镜像、容器和 Docker Compose 是容器化技术的核心组件,以下是对它们的详细解析及使用场景说明。 1、Docker 镜像(Image) 定义: 镜像是只读模板,包含运行应用程序所需的代码、…...
批量创建同名文件夹并整理文件至对应文件夹
在我们的日常工作和生活中,创建文件几乎是必不可少的一部分。随着时间的推移,电脑中积累了大量的文件,管理这些文件成为一项繁琐且耗时的任务。尤其当我们需要按照一定规则对文件进行整理时,很多人会感到困惑。例如,领…...
每日一题——数据中心网络地址规划
文章目录 数据中心网络地址规划问题描述输入格式输出格式示例输入示例输出实现思路1. IP地址转换2. 区间排序3. 动态规划 C语言完整实现(含详细注释)总结 数据中心网络地址规划 问题描述 你是一名数据中心网络地址规划人员。每个业务需要一段IP地址区间…...
如何远程访问家中服务器-FRP内网穿透详细
💡 本文会带给你 如何远程访问家中服务器FRP自动运行的方法一、准备工作 准备一台具备公网 IP 的服务器(如阿里云、腾讯云等云服务器,要求不高,几十块一年服务的轻型服务就行),用于部署 FRP 服务端(frps)。 家中电脑(内网设备),用于运行 FRP 客户端(frpc)。 下…...
el-select+vue-virtual-scroller解决数据量大卡顿问题
解决el-select中数据量过大时,显示及搜索卡顿问题,及正确的回显默认选中数据 粗略的封装了组件,有需要各种属性自定义的,自己添加设置下 环境 node 16.20.1 npm 8.19.4 vue2、element-ui "vue-virtual-scroller"…...
数码管静态显示一位字符(STC89C52单片机)
#include <reg52.h> sbit ADDR0 P1^0; sbit ADDR1 P1^1; sbit ADDR2 P1^2; sbit ADDR3 P1^3; sbit ENLED P1^4; //用数组来存储数码管的真值表,数组将在下一章详细介绍 unsigned char code LedChar[] { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82…...
明心见性与真如三昧
在佛教禅宗体系中,明心见性与真如三昧是修行者追求的核心目标。明心见性作为修行的起点,揭示了众生的真如本性;而真如三昧则是巩固和深化这一证悟的关键修行方法。二者相辅相成,构成了禅宗修行的完整路径。 一、明心见性…...
并发设计模式之双缓冲系统
双缓冲的本质是 通过空间换时间,通过冗余的缓冲区解决生产者和消费者的速度差异问题,同时提升系统的并发性和稳定性。 双缓冲的核心优势 优势具体表现解耦生产与消费生产者和消费者可以独立工作,无需直接同步。提高并发性生产者和消…...
使用谷歌浏览器自带功能将网页转换为PDF文件
将自己喜欢的技术网页转换为PDF文件有多种方法,这里介绍使用谷歌浏览器自带功能。 (本文截图仅作为演示使用) 使用谷歌浏览器自带功能 1.用Chrome浏览器,打开需要转换的网页,点击浏览器右上角的三个点(菜…...
JavaEE--2.多线程
1.认识线程(Thread) 1.1概念 1)什么是线程 ⼀个线程就是⼀个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执行着多份代码. 2)为什么要有线程 首先, "并发编程" 成为 "刚需". 1. 单核 CPU 的发展遇到…...
沐渥氮气柜控制板温湿度氧含量氮气流量四显智控系统
氮气柜控制板通常用于实时监控和调节柜内环境参数,确保存储物品如电子元件、精密仪器、化学品等,处于低氧、干燥的稳定状态。以下是沐渥氮气柜控制板核心参数的详细介绍及控制逻辑: 一、控制板核心参数显示模块 1)温度显示&am…...
线性代数-矩阵的秩
矩阵的秩(Rank)是线性代数中的一个重要概念,表示矩阵中线性无关的行(或列)的最大数量。它反映了矩阵所包含的“有效信息”的维度,是矩阵的核心特征之一。 直观理解 行秩与列秩: 行秩࿱…...
【自然语言处理与大模型】模型压缩技术之量化
在这篇文章中想和大家分享什么是量化?为什么要量化?以及如何实现量化?通过这三个基本问题,我们不仅可以全面了解量化的内涵和外延,还能更清晰地认识到它在实践中的重要性和应用价值。 一、什么是量化呢? 大…...
OneClicker脚本自动运行工具
工作的时候,有很多琐碎的事情需要重复的做 比如打开某个文件,打开某个网站,打开某个软件 这个时候可以写个自动脚本,把机械琐碎的事情交给脚本处理 但是脚本一多,不好管理,而且要选择哪个脚本也是个麻烦的事…...
Activity之间交互
Backgroud: 想要实现Activity之间的交互,需要用到intent工具 本博客中所有第二Activity均为SecActivity,需要预先进行创建 本博客所使用的开发语言为Kotlin 使用intent调用Activity 显式调用 val intent Intent(this, SecActivity::class.…...
【React】搜索时高亮被搜索选中的文案
文章目录 代码实现 代码实现 函数封装: export function highlightKeyword(input: string, keyword: string | undefined) {if (!keyword || !input || !input.includes(keyword)) return input;const startIndex input.indexOf(keyword);return React.createEle…...
MCP(Minecraft Coder Pack)完全指南:从入门到精通
1. 什么是MCP? Minecraft Coder Pack(简称MCP)是一套用于反编译、修改和重新编译Minecraft Java版源代码的工具集。它允许开发者深入研究Minecraft的底层代码,并在此基础上进行模组(Mod)开发、代码分析或自…...
stm32week12
stm32学习 九.stm32与HAL库 2.HAL库框架 总架构: 文件介绍: ppp是某一外设,ex是拓展功能 HAL库API函数和变量命名规则: HAL库对寄存器位操作的相关宏定义: HAL库的回调函数: 3.STM32启动过程 MDK编译过…...
mindspeed-rl使用注意事项
1、安装 参考1:docs/install_guide.md R1-CLM/MindSpeed-RL - Gitee.com 参考2:VLLM x Ascend框架_vllm-ascend-CSDN博客 2、SFT微调 整体参考docs/supervised_finetune.md 自定义数据格式同:AUTO-DL 910B mindspeed-llm 4层DeepSeek …...
第 4 篇:平稳性 - 时间序列分析的基石
第 4 篇:平稳性 - 时间序列分析的基石 在上一篇中,我们学习了如何将时间序列分解为趋势、季节性和残差。我们看到,很多真实世界的时间序列(比如 CO2 浓度)都包含明显的趋势(长期向上或向下)和/…...