【6】STM32·FreeRTOS·列表和列表项
目录
一、列表和列表项的简介
1.1、列表
1.2、列表项
1.3、迷你列表项
1.4、列表和列表项的关系
二、列表相关API函数介绍
2.1、初始化列表vListInitialise()
2.2、初始化列表项vListInitialiseItem()
2.3、列表插入列表项vListInsert()
2.4、列表末尾插入列表项vListInsertEnd()
2.5、列表移除列表项uxListRemove()
三、列表项的插入和删除实验
运行结果
一、列表和列表项的简介
列表:FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS 中的任务。
列表项:存放在列表中的项目
列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表
列表的特点:列表项间的地址非连续,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变
数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变
在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构
1.1、列表
有关于列表的东西均在文件 list.c 和 list.h 中,下面是 list.h 中,列表相关结构体:
typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */volatile UBaseType_t uxNumberOfItems; /* 列表中的列表项数量 */ListItem_t * configLIST_VOLATILE pxIndex; /* 用于遍历列表项的指针 */MiniListItem_t xListEnd; /* 末尾列表项 */listSECOND_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */
} List_t;
列表结构示意图
1、在该结构体中,包含了两个宏,这两个宏是确定的已知常量,FreeRTOS 通过检查这两个常量的值,来判断列表的数据在程序运行过程中,是否遭到破坏,该功能一般用于调试,默认是不开启的。
2、成员 uxNumberOfItems,用于记录列表中列表项的个数(不包含 xListEnd)
3、成员 pxIndex 用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项
4、成员变量 xListEnd 是一个迷你列表项,排在最末尾
1.2、列表项
列表项是列表中用于存放数据的地方,在 list.h 文件中,有列表项的相关结构体定义:
struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性 */configLIST_VOLATILE TickType_t xItemValue; /* 列表项的值 */struct xLIST_ITEM * configLIST_VOLATILE pxNext; /* 下一个列表项 */struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /* 上一个列表项 */void * pvOwner; /* 列表项的拥有者 */struct xLIST * configLIST_VOLATILE pxContainer; /* 列表项所在列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测列表项的数据完整性 */
};
typedef struct xLIST_ITEM ListItem_t;
列表项结构示意图
1、成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序
2、成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项
3、成员变量 pxOwner 用于指向包含列表项的对象(通常是任务控制块)
4、成员变量 pxContainer 用于指向列表项所在列表
1.3、迷你列表项
迷你列表项也是列表项,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项
struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /* 用于检测数据完整性 */configLIST_VOLATILE TickType_t xItemValue; /* 列表项的值 */struct xLIST_ITEM * configLIST_VOLATILE pxNext; /* 下一个列表项 */struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /* 上一个列表项 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
迷你列表项结构示意图
1、成员变量 xItemValue 为列表项的值,这个值多用于按升序对列表中的列表项进行排序
2、成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项
3、迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量 pxOwner 和 pxContainer,以节省内存开销
1.4、列表和列表项的关系
列表初始状态,以及即将插入的两个列表项如下:
二、列表相关API函数介绍
函数 | 描述 |
vListInitialise() | 初始化列表 |
vListInitialiseItem() | 初始化列表项 |
vListInsert() | 列表插入列表项 |
vListInsertEnd() | 列表末尾插入列表项 |
uxListRemove() | 列表移除列表项 |
2.1、初始化列表vListInitialise()
形参 | 描述 |
pxList | 待初始化列表 |
void vListInitialise( List_t * const pxList )
{/* 初始化时,列表中只有 xListEnd,因此 pxIndex 指向 xListEnd */pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /* xListEnd 的值初始化为最大值,用于列表项升序排序时,排在最后 */pxList->xListEnd.xItemValue = portMAX_DELAY;/* 初始化时,列表中只有 xListEnd,因此上一个和下一个列表项都为 xListEnd 本身 */pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/* 初始化时,列表中的列表项数量为 0(不包含 xListEnd) */pxList->uxNumberOfItems = ( UBaseType_t ) 0U;/* 初始化用于检测列表数据完整性的校验值 */listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
初始化后列表结构
2.2、初始化列表项vListInitialiseItem()
形参 | 描述 |
pxItem | 待初始化列表项 |
void vListInitialiseItem( ListItem_t * const pxItem )
{/* 初始化时,列表项所在列表设为空 */pxItem->pxContainer = NULL;/* 初始化用于检测列表项数据完整性的校验值 */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
初始化后列表项结构
2.3、列表插入列表项vListInsert()
此函数用于将待插入列表的列表项按照列表项值升序进行排序,有序地插入到列表中
形参 | 描述 |
pxList | 列表 |
pxNewListItem | 待插入列表项 |
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{ListItem_t * pxIterator;/* 获取列表项的数值依据数值升序排列 */const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;/* 检查参数是否正确 */listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );/* 如果待插入列表项的值为最大值 */if( xValueOfInsertion == portMAX_DELAY ){/* 插入的位置为列表 xListEnd 前面 */pxIterator = pxList->xListEnd.pxPrevious;}else{/* 遍历列表中的列表项,找到插入的位置 */for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd );pxIterator->pxNext->xItemValue <= xValueOfInsertion;pxIterator = pxIterator->pxNext ){}}/* 将待插入的列表项插入指定位置 */pxNewListItem->pxNext = pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious = pxNewListItem;pxNewListItem->pxPrevious = pxIterator;pxIterator->pxNext = pxNewListItem;/* 更新待插入列表项所在列表 */pxNewListItem->pxContainer = pxList;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )++;
}
2.4、列表末尾插入列表项vListInsertEnd()
此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面,是一种无序的插入方法
形参 | 描述 |
pxList | 列表 |
pxNewListItem | 待插入列表项 |
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{/* 获取列表 pxIndex 指向的列表项 */ListItem_t * const pxIndex = pxList->pxIndex;/* 检查参数是否正确 */listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );/* 更新待插入列表项的指针成员变量 */pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious = pxIndex->pxPrevious;/* Only used during decision coverage testing.(仅在决策覆盖测试中使用) */mtCOVERAGE_TEST_DELAY();/* 更新列表中原本列表项的指针成员变量 */pxIndex->pxPrevious->pxNext = pxNewListItem;pxIndex->pxPrevious = pxNewListItem;/* 更新待插入列表项的所在列表成员变量 */pxNewListItem->pxContainer = pxList;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )++;
}
2.5、列表移除列表项uxListRemove()
此函数用于将列表项从列表项所在列表中移除
形参 | 描述 |
pxItemToRemove | 待删除列表项 |
返回值 | 描述 |
整数 | 待移除列表项移除后,所在列表剩余列表项的数量 |
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{/* 获取列表项所属列表 */List_t * const pxList = pxItemToRemove->pxContainer;/* 从列表中移除列表项 */pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;/* Only used during decision coverage testing. */mtCOVERAGE_TEST_DELAY();/* 如果 pxIndex 正指向待移除的列表项 */if( pxList->pxIndex == pxItemToRemove ){/* pxIndex 指向上一个列表项 */pxList->pxIndex = pxItemToRemove->pxPrevious;}else{mtCOVERAGE_TEST_MARKER();}/* 将待移除的列表项的所在列表指针清空 */pxItemToRemove->pxContainer = NULL;/* 更新列表中列表项的数量 */( pxList->uxNumberOfItems )--;/* 返回移除后的列表中列表项的数量 */return pxList->uxNumberOfItems;
}
三、列表项的插入和删除实验
将设计三个任务:start_task、task1、task2
三个任务的功能如下
start_task:用来创建其他的 2 个任务
task1:实现 LED0 每 500ms 闪烁一次,用来提示系统正在运行
task2:调用列表和列表项相关 API 函数,并且通过串口输出相应的信息,进行观察
main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "freertos_demo.h"int main(void)
{HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */delay_init(168); /* 延时初始化 */usart_init(115200); /* 串口初始化为115200 */led_init(); /* 初始化LED */lcd_init(); /* 初始化LCD */key_init(); /* 初始化按键 */freertos_demo();
}
freertos_demo.c
#include "freertos_demo.h"/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */List_t TestList; /* 定义测试列表 */
ListItem_t ListItem1; /* 定义测试列表项1 */
ListItem_t ListItem2; /* 定义测试列表项2 */
ListItem_t ListItem3; /* 定义测试列表项3 *//******************************************************************************************************//* FreeRTOS例程入口函数 */
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "List & ListItem", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);xTaskCreate((TaskFunction_t)start_task, /* 任务函数 */(const char *)"start_task", /* 任务名称 */(uint16_t)START_STK_SIZE, /* 任务堆栈大小 */(void *)NULL, /* 传入给任务函数的参数 */(UBaseType_t)START_TASK_PRIO, /* 任务优先级 */(TaskHandle_t *)&StartTask_Handler); /* 任务句柄 */vTaskStartScheduler();
}/* start_task */
void start_task(void *pvParameters)
{taskENTER_CRITICAL(); /* 进入临界区 *//* 创建任务1 */xTaskCreate((TaskFunction_t)task1, /* 任务函数 */(const char *)"task1", /* 任务名称 */(uint16_t)TASK1_STK_SIZE, /* 任务堆栈大小 */(void *)NULL, /* 传入给任务函数的参数 */(UBaseType_t)TASK1_PRIO, /* 任务优先级 */(TaskHandle_t *)&Task1Task_Handler); /* 任务句柄 *//* 创建任务2 */xTaskCreate((TaskFunction_t)task2, /* 任务函数 */(const char *)"task2", /* 任务名称 */(uint16_t)TASK2_STK_SIZE, /* 任务堆栈大小 */(void *)NULL, /* 传入给任务函数的参数 */(UBaseType_t)TASK2_PRIO, /* 任务优先级 */(TaskHandle_t *)&Task2Task_Handler); /* 任务句柄 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL(); /* 退出临界区 */
}/* task1 */
void task1(void *pvParameters)
{while (1){LED0_TOGGLE();vTaskDelay(500);}
}/* task2 */
void task2(void *pvParameters)
{/* 第一步:初始化列表和列表项 */vListInitialise(&TestList); /* 初始化列表 */vListInitialiseItem(&ListItem1); /* 初始化列表项1 */vListInitialiseItem(&ListItem2); /* 初始化列表项2 */vListInitialiseItem(&ListItem3); /* 初始化列表项3 */ListItem1.xItemValue = 40;ListItem2.xItemValue = 60;ListItem3.xItemValue = 50;/* 第二步:打印列表和其他列表项的地址 */printf("/**************第二步:打印列表和列表项的地址**************/\r\n");printf("项目\t\t\t地址\r\n");printf("TestList\t\t0x%p\t\r\n", &TestList);printf("TestList->pxIndex\t0x%p\t\r\n", TestList.pxIndex);printf("TestList->xListEnd\t0x%p\t\r\n", (&TestList.xListEnd));printf("ListItem1\t\t0x%p\t\r\n", &ListItem1);printf("ListItem2\t\t0x%p\t\r\n", &ListItem2);printf("ListItem3\t\t0x%p\t\r\n", &ListItem3);printf("/**************************结束***************************/\r\n");printf("按下KEY0键继续!\r\n\r\n\r\n");while (key_scan(0) != KEY0_PRES){vTaskDelay(10);}/* 第三步:列表项1插入列表 */printf("/*****************第三步:列表项1插入列表******************/\r\n");vListInsert((List_t *)&TestList, /* 列表 */(ListItem_t *)&ListItem1); /* 列表项 */printf("项目\t\t\t\t地址\r\n");printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.pxNext));printf("TestList->xListEnd->pxPrevious\t0x%p\r\n", (TestList.xListEnd.pxPrevious));printf("ListItem1->pxPrevious\t\t0x%p\r\n", (ListItem1.pxPrevious));printf("/**************************结束***************************/\r\n");printf("按下KEY0键继续!\r\n\r\n\r\n");while (key_scan(0) != KEY0_PRES){vTaskDelay(10);}/* 第四步:列表项2插入列表 */printf("/*****************第四步:列表项2插入列表******************/\r\n");vListInsert((List_t *)&TestList, /* 列表 */(ListItem_t *)&ListItem2); /* 列表项 */printf("项目\t\t\t\t地址\r\n");printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.pxNext));printf("ListItem2->pxNext\t\t0x%p\r\n", (ListItem2.pxNext));printf("TestList->xListEnd->pxPrevious\t0x%p\r\n", (TestList.xListEnd.pxPrevious));printf("ListItem1->pxPrevious\t\t0x%p\r\n", (ListItem1.pxPrevious));printf("ListItem2->pxPrevious\t\t0x%p\r\n", (ListItem2.pxPrevious));printf("/**************************结束***************************/\r\n");printf("按下KEY0键继续!\r\n\r\n\r\n");while (key_scan(0) != KEY0_PRES){vTaskDelay(10);}/* 第五步:列表项3插入列表 */printf("/*****************第五步:列表项3插入列表******************/\r\n");vListInsert((List_t *)&TestList, /* 列表 */(ListItem_t *)&ListItem3); /* 列表项 */printf("项目\t\t\t\t地址\r\n");printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.pxNext));printf("ListItem2->pxNext\t\t0x%p\r\n", (ListItem2.pxNext));printf("ListItem3->pxNext\t\t0x%p\r\n", (ListItem3.pxNext));printf("TestList->xListEnd->pxPrevious\t0x%p\r\n", (TestList.xListEnd.pxPrevious));printf("ListItem1->pxPrevious\t\t0x%p\r\n", (ListItem1.pxPrevious));printf("ListItem2->pxPrevious\t\t0x%p\r\n", (ListItem2.pxPrevious));printf("ListItem3->pxPrevious\t\t0x%p\r\n", (ListItem3.pxPrevious));printf("/**************************结束***************************/\r\n");printf("按下KEY0键继续!\r\n\r\n\r\n");while (key_scan(0) != KEY0_PRES){vTaskDelay(10);}/* 第六步:移除列表项2 */printf("/*******************第六步:移除列表项2********************/\r\n");uxListRemove((ListItem_t *)&ListItem2); /* 移除列表项 */printf("项目\t\t\t\t地址\r\n");printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.pxNext));printf("ListItem3->pxNext\t\t0x%p\r\n", (ListItem3.pxNext));printf("TestList->xListEnd->pxPrevious\t0x%p\r\n", (TestList.xListEnd.pxPrevious));printf("ListItem1->pxPrevious\t\t0x%p\r\n", (ListItem1.pxPrevious));printf("ListItem3->pxPrevious\t\t0x%p\r\n", (ListItem3.pxPrevious));printf("/**************************结束***************************/\r\n");printf("按下KEY0键继续!\r\n\r\n\r\n");while (key_scan(0) != KEY0_PRES){vTaskDelay(10);}/* 第七步:列表末尾添加列表项2 */printf("/****************第七步:列表末尾添加列表项2****************/\r\n");vListInsertEnd((List_t *)&TestList, /* 列表 */(ListItem_t *)&ListItem2); /* 列表项 */printf("项目\t\t\t\t地址\r\n");printf("TestList->pxIndex\t\t0x%p\r\n", TestList.pxIndex);printf("TestList->xListEnd->pxNext\t0x%p\r\n", (TestList.xListEnd.pxNext));printf("ListItem1->pxNext\t\t0x%p\r\n", (ListItem1.pxNext));printf("ListItem2->pxNext\t\t0x%p\r\n", (ListItem2.pxNext));printf("ListItem3->pxNext\t\t0x%p\r\n", (ListItem3.pxNext));printf("TestList->xListEnd->pxPrevious\t0x%p\r\n", (TestList.xListEnd.pxPrevious));printf("ListItem1->pxPrevious\t\t0x%p\r\n", (ListItem1.pxPrevious));printf("ListItem2->pxPrevious\t\t0x%p\r\n", (ListItem2.pxPrevious));printf("ListItem3->pxPrevious\t\t0x%p\r\n", (ListItem3.pxPrevious));printf("/************************实验结束***************************/\r\n");while (1){vTaskDelay(10);}
}
freertos_demo.h
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/TIMER/btim.h"
#include "FreeRTOS.h"
#include "task.h"void freertos_demo(void);#endif
运行结果
相关文章:
【6】STM32·FreeRTOS·列表和列表项
目录 一、列表和列表项的简介 1.1、列表 1.2、列表项 1.3、迷你列表项 1.4、列表和列表项的关系 二、列表相关API函数介绍 2.1、初始化列表vListInitialise() 2.2、初始化列表项vListInitialiseItem() 2.3、列表插入列表项vListInsert() 2.4、列表末尾插入列表项vLis…...
嵌入式硬件电子电路设计(五)MOS管详解(NMOS、PMOS、三极管跟mos管的区别)
引言:在我们的日常使用中,MOS就是个纯粹的电子开关,虽然MOS管也有放大作用,但是几乎用不到,只用它的开关作用,一般的电机驱动,开关电源,逆变器等大功率设备,全部使用MOS管…...
Leetcode 最长回文子串
目录 解法1:递归算法 解法2:Map取同字母位置法 解法3:中心扩展法 解法4:动态规划法 解法5: Manacher算法 示例 1: 输入:s "babad" 输出:"bab" 解释:&quo…...
使用ENSP实现NAT
一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30 ip address 12.12.12.1 30进入e0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置…...
Elasticsearch搜索流程及原理详解
Elasticsearch搜索流程及原理详解 1. Elasticsearch概述1.1 简介1.2 核心特性1.3 应用场景2. Elasticsearch搜索流程2.1 搜索请求的发起2.2 查询的执行2.3 结果的聚合与返回3. Elasticsearch原理详解3.1 倒排索引3.2 分布式架构3.3 写入流程3.4 读取流程4. 技术细节与操作流程4…...
计算机组成原理之DMA方式
1. DMA方式的基本概念与特点 基本概念:DMA(Direct Memory Access)即直接存储器存取,是一种计算机组成原理中的数据传输模式。在此模式下,硬件可以直接从外设(如磁盘、网络设备等高速设备)读写内…...
贴代码框架PasteForm特性介绍之query,linkquery
简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…...
Linux安装RabbitMQ
安装步骤 rabbitmq使用erlang开发,依赖于erlang,所以需要先下载erlang,且版本要兼容: 可在官网查看erlang与rabbitmq的版本对应关系 https://www.rabbitmq.com/docs/which-erlangCentOs7安装运行 下载 下载地址 https://www.rab…...
C语言:函数指针精讲
1、函数指针 一个函数总是占用一段连续的内存区域,函数名在表达式中有事也会被转换为该函数所在内存区域的首地址,这和数组名非常类似,我们可以把函数这个首地址(或称入口地址)赋予一个指针变量,使指针变量…...
阿里云 DevOps 资源安全扫描实践
随着企业上云进程的加速,云资源的使用量日益增长,云环境中资源的安全性和稳定性成为了企业业务运营的关键要素 面对多样化的云资源和复杂的应用场景,传统的安全管理手段已无法完全满足企业日益严苛的安全需求。为了确保云上资源的安全性&…...
038集——quadtree(CAD—C#二次开发入门)
效果如下: using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using System; using System.Collections.Generic; using System.Linq; using System.T…...
【Python · PyTorch】循环神经网络 RNN(基础概念)
【Python PyTorch】循环神经网络 RNN(基础概念) 0. 生物学相似性1. 概念2. 延时神经网络(TDNN)3. 简单循环神经网络(Simple RNN)3.1 BiRNN 双向循环神经网络3.2 特点记忆性参数共享图灵完备 3.3 网络结构3…...
在Ubuntu系统中制作系统启动u盘
2024-11:用Ubuntu系统一段时间后,编程体验很好,命令行尤其好用。时间一长,考虑到Windows系统里面丰富的软件生态,还是颇为割舍不下,本来想着再买个主机,但是考虑到成本问题,还是给笔…...
性能监控利器:Ubuntu 22.04 上的 Zabbix 安装与配置指南
简介 今天我们来聊聊如何在 Ubuntu 22.04 上安装和配置 Zabbix。我们会用到 PostgreSQL 作为数据库后端,Nginx 作为 Web 服务器,并用 Let’s Encrypt SSL 证书来保驾护航。 什么是 Zabbix? Zabbix 是一个开源的网络监控和管理解决方案&…...
【C语言篇】从字符海洋到整数大陆——atoi 的探险之旅
文章目录 须知 💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗࿱…...
字符三角形
字符三角形 C语言代码C语言代码Java语言代码Python语言代码 💐The Begin💐点点关注,收藏不迷路💐 给定一个字符,用它构造一个底边长5个字符,高3个字符的等腰字符三角形。 输入 输入只有一行, …...
3.12MayBeSomeLinearAlgebra
X是M*(D1),XT为(D1)*M Ω是一行D1列,X乘以欧米噶是M行D1列 行是说样本个数,列是特征数量 如果是小样本,那么可能会出现特征数量大于样本个数 如果MD*DM就是M*M,...
私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?
在当今数字化、网络化的时代背景下,视频监控技术已广泛应用于各行各业,成为保障安全、提升效率的重要工具。然而,面对复杂多变的监控需求和跨区域、网络化的管理挑战,传统的视频监控解决方案往往显得力不从心。 EasyCVR视频融合云…...
小程序24-滚动效果:scroll-view组件详解
在微信小程序中如果想实现内容滚动,需要使用 scroll-view 组件 scroll-view:可滚动视图区域,适用于需要滚动展示内容的场景,用户可以通过手指滑动或者点击滚动条滚动内容。 scroll-x允许横向滚动scroll-y允许纵向滚动 实现横向…...
概念解读|K8s/容器云/裸金属/云原生...这些都有什么区别?
随着容器技术的日渐成熟,不少企业用户都对应用系统开展了容器化改造。而在容器基础架构层面,很多运维人员都更熟悉虚拟化环境,对“容器圈”的各种概念容易混淆:容器就是 Kubernetes 吗?容器云又是什么?容器…...
分层架构 IM 系统之架构演进
在电商业务日活几百万的情况下,IM 系统采用分层架构方式,如下图。 分层架构的 IM 系统,整体上包含了【终端层】、【入口层】、【业务逻辑层】、【路由层】、【数据访问层】和【存储层】,我们在上篇文章(分层架构 IM 系…...
公司金融期末考试题目
公司金融期末考试题 选择题 1.现金折扣和信用条件(教材P253) 题目类似: 下列不属于信用条件的是()。 现金折扣 数量折扣信用期限 折扣期限 给定的信用条件为"1/10,n/40",则其含义…...
Dev C++ 配置C99标准
这里写自定义目录标题 Dev C 配置C99标准 Dev C 配置C99标准 选择工具-编译选项-编译器-编译时加入以下命令-确定即可 -stdc99...
ubuntu安装Eclipse
版本 ubuntu16.04 64bitEclipse 2019-12 (太高容易崩溃)下载:wget https://archive.eclipse.org/technology/epp/downloads/release/2019-12/R/eclipse-java-2019-12-R-linux-gtk-x86_64.tar.gzjdk安装 将jdk1.8.0_211-linux-x64.tar.gz解压到…...
Android 网络请求(一)初识HTTP网络通信
学习笔记 代码样例 import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;public class HttpURLConnectionExample {public String getDataFromServer() {String result ""; // 存储请求返…...
AIOps案例剖析 | 告警收敛增强:相似告警由千化一
业务规模的指数级增长、稳敏双态共存以及云上云下架构复杂化是近几年企业客户运维部门的最大头疼点,其中告警风暴这一现象在传统AIOps的工作形式下尤难处理。 一、案例背景 某大型企业在过去一年中,业务规模实现了翻倍增长,伴随着业务的迅速…...
压缩感知理论
一、概念理解 压缩感知是什么 压缩感知(Compressed Sensing,CS)是一种基于稀疏表示的采样理论,是一种革命性的信号处理方法,它通过利用信号的稀疏性,在远低于传统采样要求的速率下捕获和重构信号。 信号的稀疏性和压缩感知的关系 信号的稀疏…...
深度学习实验十二 卷积神经网络(3)——基于残差网络实现手写体数字识别实验
目录 一、模型构建 1.1残差单元 1.2 残差网络的整体结构 二、统计模型的参数量和计算量 三、数据预处理 四、没有残差连接的ResNet18 五、带残差连接的ResNet18 附:完整的可运行代码 实验大体步骤: 先前说明: 上次LeNet实验用到的那…...
关于SpringBoot集成Kafka
关于Kafka Apache Kafka 是一个分布式流处理平台,广泛用于构建实时数据管道和流应用。它能够处理大量的数据流,具有高吞吐量、可持久化存储、容错性和扩展性等特性。 Kafka一般用作实时数据流处理、消息队列、事件架构驱动等 Kafka的整体架构 ZooKeeper:…...
windows C#-取消任务列表(上)
如果不想等待异步控制台应用程序完成,可以取消该应用程序。 通过遵循本文的示例,可将取消添加到下载网站内容的应用程序。 可通过将 CancellationTokenSource 实例与每个任务进行关联来取消多个任务。 如果选择 Enter 键,则将取消所有尚未完成…...
RabbitMQ4:work模型
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
《筑牢安全防线:培养 C++安全编程思维习惯之道》
在当今数字化飞速发展的时代,软件安全的重要性已提升到前所未有的高度。C作为一种广泛应用于系统开发、游戏制作、高性能计算等众多领域的编程语言,其程序的安全性更是关乎重大。培养 C安全编程的思维习惯,不仅是开发者个人能力提升的关键&am…...
Python Flask中集成SQLAlchemy和Flask-Login
在现代Web应用开发中,数据库和用户认证是两个非常重要的功能。Flask作为一个轻量级的Python Web框架,本身只提供了最基本的Web功能。但是,它可以通过集成各种优秀的扩展库来增强功能。本文将介绍如何在Flask应用中集成SQLAlchemy(数据库)和Flask-Login(用户认证),并提供一个完整…...
Kafka 生产者优化与数据处理经验
Kafka:分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析:…...
web——sqliabs靶场——第十二关——(基于错误的双引号 POST 型字符型变形的注入)
判断注入类型 a OR 1 1# 发现没有报错 ,说明单引号不是闭合类型 测试别的注入条件 a) OR 1 1# a)) OR 1 1# a" OR 11 发现可以用双引号闭合 发现是")闭合 之后的流程还是与11关一样 爆破显示位 先抓包 是post传参,用hackbar来传参 unam…...
Spring |(二)IoC相关内容 | bean
文章目录 📚bean基础配置🐇bean的id和class🐇bean的name属性🐇bean作用范围scope配置🐇bean基础配置小结 📚bean实例化🐇构造方法实例化(常用)🐇静态工厂实例…...
flux的版本
1.flux1-dev.safetensors https://huggingface.co/black-forest-labs/FLUX.1-devhttps://huggingface.co/black-forest-labs/FLUX.1-dev原生的23.8G的模型。原生12B的模型,float16的。需要配合ae.safetensors,flux1-dev.safetensors以及clip-l和T5的权重使用,注意ae.sft和f…...
基于Springboot+Vue的房屋系统 (含源码数据库)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 该系统…...
【Bluedroid】A2DP SINK播放流程源码分析
在Bluedroid协议栈中,A2DP(Advanced Audio Distribution Profile)SINK播放流程是一个复杂但有序的过程,它涉及多个层次和组件的交互。 一、概述 1.1. 初始化流程 在A2DP SINK播放之前,系统需要进行一系列初始化操作,以确保A2DP SINK服务能够正确运行。这些操作包括启动…...
【什么是Redis?】
Redis:高性能内存数据库的深度探索 在当今这个数据驱动的世界里,数据库的选择直接关系到应用程序的性能、可扩展性和可靠性。在众多数据库解决方案中,Redis以其卓越的性能、丰富的数据结构和灵活的使用场景脱颖而出,成为众多开发…...
TCL大数据面试题及参考答案
Mysql 索引失效的场景 对索引列进行运算或使用函数:当在索引列上进行数学运算、函数操作等,索引可能失效。例如,在存储年龄的列上建立了索引,若查询语句是 “SELECT * FROM table WHERE age + 1 = 20”,这里对索引列 age 进行了加法运算,数据库会放弃使用索引而进行全表扫…...
提高总线数据传输率
提高总线数据传输率是一个涉及多个方面的技术问题,以下是一些有效的方法: 一、提高总线时钟频率 总线时钟频率是影响总线传输速率的重要因素之一。通过提高总线时钟频率,可以缩短每个时钟周期的时间,从而在相同的时间内传输更多…...
_FYAW智能显示控制仪表的简单使用_串口通信
一、简介 该仪表可以实时显示位移传感器的测量值,并可设定阈值等。先谈谈简单的使用方法,通过说明书,我们可以知道长按SET键可以进入参数选择状态,按“↑”“↓”可以选择该组参数的上一个或者下一个参数。 从参数一览中可以看到有…...
图的遍历。
图的遍历这一部分,离不开广度优先和深度优先,如果大家已经学过搜索算法的话,这部分将是易如反掌。 万能搜索算法-CSDN博客 文章中不会提太多离散数学中图的专有名词,因为本篇博客只涉及最简单的图的遍历,故以练习题为主…...
Methode Electronics EDI 需求分析
Methode Electronics 是一家总部位于美国的全球性技术公司,专注于设计和制造用于多个行业的电子和电气组件,产品涵盖汽车、工业、电信、医疗设备以及消费电子等多个领域,提供创新的解决方案。 填写Methode_EDI_Parameters_Template Methode_…...
IT资产管理工具-NetBox
IT资产管理工具-NetBox 推荐一款IT资产管理工具 了解推荐阅读官方中文文档 https://docs.wangluohe.com/introduction/ 硬件要求 - 建议4Core 8G以上,100G存储空间 这里我使用的Linux镜像为 CentOS8-Stream 提前关闭Selinux和防火墙 部署NetBox 一&#…...
uniapp接入BMapGL百度地图
下面代码兼容安卓APP和H5 百度地图官网:控制台 | 百度地图开放平台 应用类别选择《浏览器端》 /utils/map.js 需要设置你自己的key export function myBMapGL1() {return new Promise(function(resolve, reject) {if (typeof window.initMyBMapGL1 function) {r…...
AWTK 最新动态:支持鸿蒙系统(HarmonyOS Next)
HarmonyOS是全球第三大移动操作系统,有巨大的市场潜力,在国产替代的背景下,机会多多,AWTK支持HarmonyOS,让AWTK开发者也能享受HarmonyOS生态的红利。 AWTK全称为Toolkit AnyWhere,是ZLG倾心打造的一套基于C…...
React基础知识一
写的东西太多了,照成csdn文档编辑器都开始卡顿了,所以分篇写。 1.安装React 需要安装下面三个包。 react:react核心包 react-dom:渲染需要用到的核心包 babel:将jsx语法转换成React代码的工具。(没使用jsx可以不装)1.1 在html中…...
Oracle热备过程中对数据库崩溃的处理方法
引言 在热备过程中如果发生数据库崩溃、断电等情况该如何处理? 如果正在备份 users 表空间的数据文件过程中,此时的数据文件表头 SCN 会被锁定,此时正在复制数据文件时数据库崩溃,系统断电。 从而导致数据文件表头与控制文件中的不一致,导致数据库无法打开,会要求介质恢…...