ESP32学习笔记_FreeRTOS(6)——Event and Notification
摘要(From AI):
这篇博客详细介绍了 FreeRTOS 中的事件组和任务通知机制,讲解了事件组如何通过位操作实现任务间的同步与通信,以及任务如何通过通知机制进行阻塞解除和数据传递。博客提供了多个代码示例,展示了如何使用事件组和任务通知在多任务环境中实现任务同步,特别适用于任务间的依赖关系和信号传递
前言:本文档是本人在依照B站UP:Michael_ee的视频教程进行学习时所做的学习笔记,可能存在疏漏和错误,如有发现,敬请指正。
文章目录
- Event Group
- Event Group Wait
- xEventGroupCreate()
- xEventGroupSetBits()
- xEventGroupWaitBits()
- Example Code:Event Group Synchronization with Multiple Tasks
- Event Group Sync
- xEventGroupSync()
- Example Code:Event Group Synchronization
- Notification
- Notification Sync
- xTaskNotifyGive()
- ulTaskNotifyTake()
- Example Code:Simple Task Notification in FreeRTOS
- Notification Value
- xTaskNotify()
- xTaskNotifyWait()
- Example Code:Task Notification with Conditional Actions Based on Values
参考资料
Michael_ee 视频教程
freeRTOS官网
espressif 在线文档
Event Group
事件组是一种同步机制,用于任务之间的通信。它们允许任务设置、清除和等待多个事件的组合
每个事件组有多个位,任务可以操作这些位来表示不同的状态或事件。
关键功能
位操作事件组可以被看作是一个二进制位的集合,任务可以对这些位进行设置、清除和等待同步机制任务可以等待事件组中的某些位变为设定状态(例如,位为1),这样可以使任务在等待某些事件发生时暂停执行,直到事件发生多任务通信事件组可以在多个任务之间传递信息
使用场景
- 在多个任务之间传递控制信号或数据标志
- 实现任务之间的依赖关系,如任务A完成某项工作后,任务B才可以执行
Event Group Wait
xEventGroupCreate()
创建一个新的事件组,并返回可以引用创建的事件组的句柄
事件组包含的标志位(或位)的数量依赖于 configUSE_16_BIT_TICKS 配置项
-
如果
configUSE_16_BIT_TICKS = 1,则事件组有 8 位(标志位) -
如果
configUSE_16_BIT_TICKS = 0,则事件组有 24 位(标志位) -
配置文件路径(v5.3.1)
idf\v5.3.1\esp-idf\components\freertos\config\include\freertos
#include "FreeRTOS.h"
#include "event_groups.h"EventGroupHandle_t xEventGroupCreate( void );
返回值
EventGroupHandle_t创建了事件组,返回的值是创建的事件组的句柄
NULL无法创建事件组,因为可用的 FreeRTOS 堆内存不足
xEventGroupSetBits()
在RTOS事件组中设置位
- 这个函数不能从中断中调用
#include "FreeRTOS.h"
#include "event_groups.h"EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet );
参数
xEventGroup需要设置 bit 的事件组
uxBitsToSet一个按位的值,表示要在事件组中设置的一个或多个位
-
通过设置不同的二进制值来指定要等待的位
- 如果想等待 bit 0 和 bit 2 设置,
uxBitsToWaitFor 应该是0x05(即00000101) - 如果想等待 bit 0、bit 1 和 bit 2 设置,
uxBitsToWaitFor 应该是0x07(即00000111)
- 如果想等待 bit 0 和 bit 2 设置,
-
可以根据需求组合多个位来构造不同的掩码值
返回值
EventBits_t事件组中各位(bits)在调用 xEventGroupSetBits() 函数返回时的状态
可能被改变状态的情况
-
自动清除(
xClearBitsOnExit 参数- 当调用
xEventGroupSetBits() 设置位后,可能有任务正在等待这些位(通过xEventGroupWaitBits()),如果等待任务设置了xClearBitsOnExit 参数为pdTRUE,则这些位在任务被唤醒时会自动被清除,在xEventGroupSetBits() 返回时,返回值中的位可能已经被清除
- 当调用
-
高优先级 Task 清除位
- 如果设置事件位后,有更高优先级的任务因这些位的设置从阻塞状态切换为就绪状态(Ready),并立即执行,它可能会修改事件组的值
在 xEventGroupSetBits() 返回时,返回值可能反映的是任务执行后事件组的状态,而不是立即设置位后的状态
xEventGroupWaitBits()
读取RTOS事件组中的位,可选择进入阻塞状态(带超时)以等待一个位或一组位被设置
- 这个函数不能从中断中调用
#include "FreeRTOS.h"
#include "event_groups.h"EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
参数
xEventGroup需要测试(查看)bit 的事件组
uxBitsToWaitFor一个位运算值,用于指定在事件组中要等待的位
- 不能被设置为
0
xClearOnExit设置是否清除事件
-
pdTRUE- 如果设置为
pdTRUE,那么在函数返回时,事件组中由 uxBitsToWaitFor 指定的那些位会被清除(即设置为 0),前提是函数返回的原因不是超时 - 这通常用于在检测到某些事件发生后,自动清除事件状态,避免其他任务误判这些事件仍然有效。
- 如果设置为
-
pdFALSE- 如果设置为
pdFALSE,事件组中的位不会被清除,即便函数成功返回。这种方式适用于需要让其他任务也能检测到这些位的场景
- 如果设置为
xWaitForAllBits决定任务等待位时的逻辑条件是 逻辑 AND(等待所有指定的位都被设置)还是 逻辑 OR(只需等待任意一个指定的位被设置)
-
pdTRUE(逻辑 AND)- 函数会等待事件组中的所有指定位都被设置为 1
- 如果所有位在等待时间内都被设置,函数返回
- 如果等待时间到期(
xTicksToWait 超时),函数返回超时结果
-
pdFALSE(逻辑 OR)- 函数会等待事件组中的任意一个指定位被设置为 1
- 如果任意一位在等待时间内被设置,函数立即返回
- 如果等待时间到期且没有任何位被设置,函数返回超时结果
xTicksToWait等待一个/全部 bit 的最大时间
返回值
EventBits_t事件组的当前值,这个值表示函数返回时,事件组中哪些位(bits)是被设置(1)的
Example Code:Event Group Synchronization with Multiple Tasks
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"#include "freeRTOS/event_groups.h"EventGroupHandle_t eventGroup;#define BIT_0 (1 << 0)
#define BIT_4 (1 << 4)void Task1(void *pvParam)
{printf("Task1 is running\n");while (true){printf("Task1 is begin to wait\n");// xEventGroupWaitBits(eventGroup, BIT_0 | BIT_4, pdTRUE, pdFALSE, portMAX_DELAY);// // 检测第一位和第四位是否被设置,如果设置则唤醒Task1// // 检测完成后,第一位和第四位将被清除// printf("BIT_0 or BIT_4 is set, Task1 is woken up\n");xEventGroupWaitBits(eventGroup, BIT_0 | BIT_4, pdTRUE, pdTRUE, portMAX_DELAY);printf("BIT_0 or BIT_4 is set, Task1 is woken up\n");vTaskDelay(pdMS_TO_TICKS(1000));}
}void Task2(void *pvParam)
{printf("Task2 is running\n");vTaskDelay(pdMS_TO_TICKS(1000));while (true){printf("Task2 is begin to set bit0\n");xEventGroupSetBits(eventGroup, BIT_0);vTaskDelay(pdMS_TO_TICKS(5000));printf("Task2 is begin to set bit4\n");xEventGroupSetBits(eventGroup, BIT_4);vTaskDelay(pdMS_TO_TICKS(5000));}
}void app_main(void)
{eventGroup = xEventGroupCreate(); // 创建事件组if (eventGroup == NULL){printf("Event group creation failed\n");}else{vTaskSuspendAll();xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, 1, NULL, 0);xTaskCreatePinnedToCore(Task2, "Task2", 2048, NULL, 1, NULL, 0);xTaskResumeAll();}
}
Event Group Sync
wait和sync的不同:
wait
等待事件组的 Task(设为 waitTask) 在进入 wait 状态后,等待设置事件组的 Task(设为 setTask)对事件组进行设置,waitTask 在检测到事件组满足要求后继续运行,setTask 在调用xEventGroupSetBits()后不阻塞,继续运行
sync
setTask 在设置事件组的目标位后进入阻塞状态,等待其它 setTask 对事件组进行设置,当满足各 setTask 对事件组的要求后,所有进入阻塞状态的 setTask 同时进入运行状态
即 setTask 在设置事件组之后也在 wait 事件组
xEventGroupSync()
在事件组中设置位,然后等待在同一事件组中设置位的组合
此功能通常用于同步多个任务(通常称为任务集合),其中每个任务在继续之前必须等待其他任务到达同步点
如果uxBitsToWaitFor参数指定的位被设置或在该时间内被设置,则该函数将在其时间到期之前返回,这种情况下,由uxBitsToWaitFor指定的所有位将在函数返回之前自动清除
这个函数不能从中断中调用
#include "FreeRTOS.h"
#include "event_groups.h"EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait );
参数
xEventGroup需要设置 bit 的时间组
uxBitsToSet一个位运算值,用于指定在事件组中要设置的位
uxBitsToWaitFor一个位运算值,用于指定在事件组中要等待的位
xTicksToWait等待 bits 的最大时间
返回值
EventBits_t表示事件组的状态,具体包括以下两种情况:
-
等待的位被设置
- 如果
xEventGroupSync() 返回是因为所有等待的位被设置,则返回值是事件组中这些位在被清除前的状态
- 如果
-
超时到期
- 如果
xEventGroupSync() 返回是因为超时时间到期,则可能并非所有等待的位都被设置,返回值表示超时时事件组的状态
- 如果
Example Code:Event Group Synchronization
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"#include "freeRTOS/event_groups.h"EventGroupHandle_t eventGroup;#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
#define BIT_2 (1 << 2)
#define ALL_SYNC_BITS (BIT_0 | BIT_1 | BIT_2)void Task0(void *pvParam)
{printf("Task0 is running\n");while (true){vTaskDelay(pdMS_TO_TICKS(1000));printf("Task0 set BIT_0\n");xEventGroupSync(eventGroup, BIT_0, ALL_SYNC_BITS, portMAX_DELAY); // 设置 BIT_0,进入同步等待printf("Task0 sync\n");vTaskDelay(pdMS_TO_TICKS(5000));}
}void Task1(void *pvParam)
{printf("Task1 is running\n");while (true){vTaskDelay(pdMS_TO_TICKS(3000));printf("Task1 set BIT_1\n");xEventGroupSync(eventGroup, BIT_1, ALL_SYNC_BITS, portMAX_DELAY);printf("Task1 sync\n");vTaskDelay(pdMS_TO_TICKS(5000));}
}void Task2(void *pvParam)
{printf("Task2 is running\n");while (true){vTaskDelay(pdMS_TO_TICKS(6000));printf("Task2 set BIT_2\n");xEventGroupSync(eventGroup, BIT_2, ALL_SYNC_BITS, portMAX_DELAY);printf("Task2 sync\n");vTaskDelay(pdMS_TO_TICKS(5000));}
}void app_main(void)
{eventGroup = xEventGroupCreate(); // 创建事件组if (eventGroup == NULL){printf("Event group creation failed\n");}else{vTaskSuspendAll();xTaskCreatePinnedToCore(Task0, "Task0", 2048, NULL, 1, NULL, 0);xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, 1, NULL, 0);xTaskCreatePinnedToCore(Task2, "Task2", 2048, NULL, 1, NULL, 0);xTaskResumeAll();}
}
Notification
每个任务都有一个 32 位的通知值,该值在任务创建时初始
任务通知是直接发送给任务的事件,它可以解除接收任务的阻塞,并可选择更新接收任务的通知值
通知值有两种用法:按位、增量
Notification Sync
xTaskNotifyGive()
使目标任务的通知值递增
- RTOS 任务通知功能在默认情况下是启用的,并且可以从构建中排除(每个任务节省8字节)通过在
FreeRTOSConfig.h 设置configUSE_TASK_NOTIFICATIONS为0
#include "FreeRTOS.h"
#include "task.h"BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
参数
xTaskToNotify被通知的任务的句柄,其通知值递增(增量用法)
返回值
总是返回pdPASS
ulTaskNotifyTake()
任务可以使用 ulTaskNotifyTake() 来选择性地阻塞,等待通知值变为非零,在任务的通知值不为零时返回
在退出时可以选择将通知值清零(此时通知值类似于二值信号量)或将通知值递减(此时通知值更像计数信号量)
#include "FreeRTOS.h"
#include "task.h"uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
参数
xClearCountOnExit
-
pdFALSE- 每次成功调用后通知值减 1,类似计数信号量的效果
-
pdTRUE- 每次成功调用后通知值重置为 0,类似二值信号量的效果
xTicksToWait等待通知的最大时间
返回值
任务的通知值在被递减或清除之前的值
Example Code:Simple Task Notification in FreeRTOS
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"#include "freeRTOS/event_groups.h"TaskHandle_t task0Handle = NULL;
TaskHandle_t task1Handle = NULL;void Task0(void *pvParam)
{printf("Task0 is running\n");while (true){printf("Task0 is waitting for notification\n");ulTaskNotifyTake(pdTRUE, portMAX_DELAY);printf("Task0 got notification\n"); // Task0 等待 Task1 的通知vTaskDelay(pdMS_TO_TICKS(1000));}
}void Task1(void *pvParam)
{printf("Task1 is running\n");vTaskDelay(pdMS_TO_TICKS(5000));while (true){printf("Task1 is sending notification\n");xTaskNotifyGive(task0Handle); // Task1 通知 Task0vTaskDelay(pdMS_TO_TICKS(5000));}
}void app_main(void)
{vTaskSuspendAll();xTaskCreatePinnedToCore(Task0, "Task0", 2048, NULL, 1, &task0Handle, 0);xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, 1, &task1Handle, 0);xTaskResumeAll();
}
Notification Value
xTaskNotify()
用于直接向任务发送事件并解除阻塞,并可选地以以下方式之一更新接收任务的通知值
- 将一个 32 位的数字写入通知值
- 增加一个(增量)通知值
- 设置一个或多个通知值
- 保持通知值不变
#include "FreeRTOS.h"
#include "task.h"BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
参数
xTaskToNotify被通知的 Task 句柄
ulValue用于更新被通知任务的通知值,如何解释 ulValue 取决于 eAction 参数的值
eAction
eNoAction任务被通知,但通知值不变eSetBits任务的通知值与 ulValue 进行按位或(or) 操作eIncrement任务的通知值加 1eSetValueWithOverwrite任务的通知值被无条件设置为 ulValue,即使之前已经有通知eSetValueWithoutOverwrite如果任务已经有通知待处理,则通知值不会被改变,xTaskNotify() 将返回pdFAIL;如果任务没有待处理的通知,则其通知值会被设置为ulValue
返回值
在除eSetValueWithoutOverwrite所有其他情况下,返回 pdPASS
xTaskNotifyWait()
如果接收任务已经被阻塞并等待通知,当一个通知到达时,接收任务将从阻塞状态移除并清除通知
#include "FreeRTOS.h"
#include "task.h"BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
参数
ulBitsToClearOnEntry
- 在调用
xTaskNotifyWait() 时,通知值中的某些位会在函数进入时被清除 - 如果
ulBitsToClearOnEntry 设置为 0x01,则任务通知值中的第 0 位会在函数进入时被清除 - 如果设置为
0xffffffff(ULONG_MAX),则通知值的所有位都会被清除,相当于将通知值重置为 0 - 注意:仅当调用时没有挂起的通知时,清除操作才会执行
ulBitsToClearOnExit
- 在接收到通知后,在函数退出前通知值中的某些位会被清除
- 如果设置为
0xffffffff(ULONG_MAX),则通知值的所有位都会被清除
pulNotificationValue
- 用于将任务的通知值传递给调用者
- 保存的是 在清除
ulBitsToClearOnExit的位之前的通知值 - 如果不需要获取通知值,可以将其设置为
NULL
xTicksToWait最大等待时间
返回值
pdTRUE接收到了通知,或在调用时通知已挂起pdFALSE在等待超时时间内没有接收到通知
Example Code:Task Notification with Conditional Actions Based on Values
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"#include "freeRTOS/event_groups.h"TaskHandle_t task0Handle = NULL;
TaskHandle_t task1Handle = NULL;void Task0(void *pvParam)
{printf("Task0 is running\n");uint32_t notifiedValue = 0;while (true){xTaskNotifyWait(0x00, 0xffffffff, ¬ifiedValue, portMAX_DELAY);if (notifiedValue == 0x00000001) // 当接收到的通知值为 0x01 时,执行相应操作{printf("Task0 get notification: bit_0\n");}else if (notifiedValue == 0x00000002){printf("Task0 get notification: bit_1\n");}else if (notifiedValue == 0x00000004){printf("Task0 get notification: bit_2\n");}else{printf("Task0 get notification: unknown\n");}vTaskDelay(pdMS_TO_TICKS(3000));}
}void Task1(void *pvParam)
{printf("Task1 is running\n");vTaskDelay(5000 / portTICK_PERIOD_MS);while (true){printf("Task1 is sending notification\n");xTaskNotify(task0Handle, 0x01, eSetValueWithOverwrite); // 发送 bit_0,覆盖之前的值vTaskDelay(5000 / portTICK_PERIOD_MS);xTaskNotify(task0Handle, 0x02, eSetValueWithOverwrite);vTaskDelay(5000 / portTICK_PERIOD_MS);xTaskNotify(task0Handle, 0x03, eSetValueWithOverwrite);vTaskDelay(5000 / portTICK_PERIOD_MS);xTaskNotify(task0Handle, 0x04, eSetValueWithOverwrite);vTaskDelay(5000 / portTICK_PERIOD_MS);}
}void app_main(void)
{vTaskSuspendAll();xTaskCreatePinnedToCore(Task0, "Task0", 2048, NULL, 1, &task0Handle, 0);xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, 1, &task1Handle, 0);xTaskResumeAll();
}
相关文章:
ESP32学习笔记_FreeRTOS(6)——Event and Notification
摘要(From AI): 这篇博客详细介绍了 FreeRTOS 中的事件组和任务通知机制,讲解了事件组如何通过位操作实现任务间的同步与通信,以及任务如何通过通知机制进行阻塞解除和数据传递。博客提供了多个代码示例,展示了如何使用事件组和任务通知在多任…...
力扣-数组-350 两个数组的交集Ⅱ
解析 与刚刚的《两个数组的交集》一样,只是这道题允许重复,将上一题的set去除即可。 代码 class Solution { public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {vector<int> res;int index1 …...
云原生第二次练习
1.判断192.168.1.0/24网络中,当前在线的ip有哪些,并编写脚本打印出来。 #!/bin/bash for ip in $(seq 1 254); doping -c 1 -W 1 "192.168.1.$ip" > /dev/null 2>&1if [ $? -eq 0 ]; thenecho "192.168.1.$ip is online&qu…...
SpringMVC复习笔记
文章目录 SpringMVC 概念和基本使用SpringMVC 简介SpringMVC 核心组件和调用流程SpringMVC 基本使用第一步:导入依赖第二步:Controller 层开发第三步:SpringMVC 配置类配置核心组件第四步:SpringMVC 环境搭建第五步:部…...
前端小案例——网页井字棋
前言:我们在学习完了HTML、CSS和JavaScript之后,就会想着使用这三个东西去做一些小案例,不过又没有什么好的案例让我们去练手,本篇文章就提供里一个案例——网页井字棋。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可…...
ComfyUI-PromptOptimizer:文生图提示优化节点
ComfyUI-PromptOptimizer 是 ComfyUI 的一个自定义节点,旨在优化文本转图像模型的提示。它将用户输入的提示转换为更详细、更多样化、更生动的描述,使其更适合生成高质量的图像。无需本地模型。 1、功能 提示优化:优化用户输入的提示以生成…...
AudioGPT全新的 音频内容理解与生成系统
AudioGPT全新的 音频内容理解与生成系统 ChatGPT、GPT-4等大型语言模型 (LLM) 在语言理解、生成、交互和推理方面表现出的非凡能力,引起了学界和业界的极大关注,也让人们看到了LLM在构建通用人工智能 (AGI) 系统方面的潜力。 现有的GPT模型具有极高的语言生成能力,是目前最…...
thinkphp6 + redis实现大数据导出excel超时或内存溢出问题解决方案
redis下载安装(window版本) 参考地址:https://blog.csdn.net/Ci1693840306/article/details/144214215 php安装redis扩展 参考链接:https://blog.csdn.net/jianchenn/article/details/106144313 解决思路:࿰…...
Hexo + NexT + Github搭建个人博客
文章目录 一、 安装二、配置相关项NexT config更新主题主题样式本地实时预览常用命令 三、主题设置1.侧边栏2.页脚3.帖子发布字数统计 4.自定义自定义页面Hexo 的默认页面自定义 404 页自定义样式 5.杂项搜索服务 四、第三方插件NexT 自带插件评论系统阅读和访问人数统计 五、部…...
使用Sum计算Loss和解决梯度累积(Gradient Accumulation)的Bug
使用Sum计算Loss和解决梯度累积的Bug 学习 https://unsloth.ai/blog/gradient:Bugs in LLM Training - Gradient Accumulation Fix 这篇文章的记录。 在深度学习训练过程中,尤其是在大批量(large batch)训练中,如何高…...
基于本地消息表实现分布式事务
假设我们有一个电商系统,包含订单服务和库存服务。当用户下单时,需要在订单服务中创建订单,同时在库存服务中扣减库存。这是一个典型的分布式事务场景,我们需要保证这两个操作要么都成功,要么都失败,以保证数据的最终一致性。 项目结构: 订单服务(Order Service)库存服务(Inv…...
Web3与加密技术的结合:增强个人隐私保护的未来趋势
随着互联网的快速发展,个人隐私和数据安全问题越来越受到关注。Web3作为新一代互联网架构,凭借其去中心化的特性,为个人隐私保护提供了全新的解决方案。而加密技术则是Web3的重要组成部分,进一步增强了隐私保护的能力。本文将探讨…...
广播网络实验
1 实验内容 1、构建星性拓扑下的广播网络,实现hub各端口的数据广播,验证网络的连通性并测试网络效率 2、构建环形拓扑网络,验证该拓扑下结点广播会产生数据包环路 2 实验流程与结果分析 2.1 实验环境 ubuntu、mininet、xterm、wireshark、iperf 2.2 实验方案与结果分析…...
Vscode——SSH连接不上的一种解决办法
一、完整报错: > @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ > IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! > Someone could be eavesdropping on you right now (man-in-the...
ChatGPT大模型极简应用开发-目录
引言 要理解 ChatGPT,了解其背后的 Transformer 架构和 GPT 技术一路的演进则变得非常必要。 ChatGPT 背后的 LLM 技术使普通人能够通过自然语言完成过去只能由程序员通过编程语言实现的任务,这是一场巨大的变革。然而,人类通常容易高估技术…...
EI Scopus双检索 | 2025年第四届信息与通信工程国际会议(JCICE 2025)
会议简介 Brief Introduction 2025年第四届信息与通信工程国际会议(JCICE 2025) 会议时间:2025年7月25日-27日 召开地点:中国哈尔滨 大会官网:www.jcice.org 由黑龙江大学和成都信息工程大学主办,江苏科技大学协办的2025年第四届信…...
重学SpringBoot3-Spring Retry实践
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞??收藏评论 重学SpringBoot3-Spring Retry实践 1. 简介2. 环境准备3. 使用方式 3.1 注解方式 基础使用自定义重试策略失败恢复机制重试和失败恢复效果注意事项 3.2 编程式使用3.3 监听重试过程 监…...
TiDB 和 MySQL 的关系:这两者到底有什么不同和联系?
TiDB 和 MySQL 的关系:这两者到底有什么不同和联系? 在了解 TiDB 和 MySQL 之间的关系时,很多人可能会有疑问:这两个数据库到底有什么区别和联系?是不是 TiDB 就是 MySQL 的升级版?或者 TiDB 是一种“替代…...
【Java】JDK17的下载安装(与JDK1.8相互切换)
本文以参考以下链接为主:JDK17 如果上述操作不生效,请看以下操作: 添加以下变量并移动到最上面即可...
CSS3 3D 转换介绍
CSS3 中的 3D 转换提供了一种在二维屏幕上呈现三维效果的方式,主要包括translate3d、rotate3d、scale3d等转换函数,下面来详细介绍: 1. 3D 转换的基本概念 坐标系 在 CSS3 的 3D 空间中,使用的是右手坐标系。X 轴是水平方向&…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
