freeRTOS总结(六)列表及列表项

1,列表和列表项的简介(熟悉)

1、列表就是一个双向循环链表,列表项就是其中的节点
2、其用途就是在三大链表(挂起、阻塞、就绪)中将任务(列表项)进行排序管理。
列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。
在这里插入图片描述
列表的特点:列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加的个数决定的,随时可以改变
数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后期无法改变
在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构
有关于列表的东西均在文件 list.c 和 list.h 中,首先我们先看下在list.h中的,

1.1列表相关结构体:

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列表项相关结构体:

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 为列表项的值,这个值多用于按升序对列表中的列表项进行排序
(当这个列表项插入某个列表时排序使用,确定插在哪
比如一个任务是10一个任务20(不是任务名这个值不同人物到不同状态时可能不一样)按升序排序20排在10后。
2、成员变量 pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项、
3、成员变量 pxOwner 用于指向包含列表项的对象(通常是任务控制块) 这个列表项代表哪个任务
4、成员变量 pxContainer 用于指向列表项所在列表。 (当前任务的列表项在哪个列表 ,该任务处于什么状态。)
在这里插入图片描述

1.3迷你列表项

就是用于标记我是最后一个列表了,你最大也得在我前面插入因为我是ffffffff最大
迷你列表项也是列表项,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项

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插入时 1的上一个下一个指向末尾 末尾的上一个下一个也指向1
2插入时 比较xItemValue的大小2比1大在1后面 1的下一个指向2上一个指向尾 2的上一个指向1下一个指向尾,尾的上一个指向2下一个指向1。

2 列表相关API函数

初始化列表
vListInitialise()
无返回值参数为初始化的列表项

void vListInitialise( List_t * const pxList )
{
	//列表中的便利指针指向末尾列表项
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); 
    //末尾列表项的排序值设置为最大
    pxList->xListEnd.xItemValue = portMAX_DELAY;
    //末尾列表项指向下个列表的指针指向自身
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );     
    //末尾列表项指向上个列表的指针指向自身
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); 
	//列表中列表项数目设置为0
    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
	/* 初始化用于检测列表数据完整性的校验值 */
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

在这里插入图片描述
初始化列表项
vListInitialiseItem()
无返回值 参数待初始化的列表项

void vListInitialiseItem( ListItem_t * const pxItem )
{
   //所属列表为NULL
    pxItem->pxContainer = NULL;

  /* 初始化用于检测列表项数据完整性的校验值 */
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

在这里插入图片描述
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 )
    {
    //将列表项的末尾列表的上一个列表指向这个临时列表
        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;
	//列表项数目加1
    ( pxList->uxNumberOfItems )++;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
vListInsertEnd()
此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面是一种无序的插入方法

void vListInsertEnd( List_t * const pxList,
                     ListItem_t * const pxNewListItem )
{
	//声明一个列表项并将当前列表指向的列表项赋值给它
    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 )++;
}

在这里插入图片描述
uxListRemove()
此函数用于将列表项从列表项所在列表中移除
参数 :待移除的列表项
返回值:移除后当前列表所剩列表项数目

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
	//声明一个列表赋值当前列表项所在列表值
    List_t * const pxList = pxItemToRemove->pxContainer;
	//移除当前列表项
    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
    mtCOVERAGE_TEST_DELAY();
	//如果当前指针指向该列表项
    if( pxList->pxIndex == pxItemToRemove )
    {
    //让他指向它的前一个
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }
	//所属列表为NULL
    pxItemToRemove->pxContainer = NULL;
    //列表项数目-1并返回
    ( pxList->uxNumberOfItems )--;

    return pxList->uxNumberOfItems;
}

在这里插入图片描述

实验 列表项的插入和删除实验(掌握)

1、实验目的:学会对FreeRTOS 列表和列表项的操作函数使用,并观察运行结果和理论分析是否一致
2、实验设计:将设计三个任务:start_task、task1、task2
三个任务的功能如下:
start_task:用来创建其他的2个任务
task1:实现LED0每500ms闪烁一次,用来提示系统正在运行
task2:调用列表和列表项相关API函数,并且通过串口输出相应的信息,进行观察
在这里插入图片描述

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 移植实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 F407电机开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );


#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t   task1_handler;
void task1( void * pvParameters );


#define TASK2_PRIO         3
#define TASK2_STACK_SIZE   128
TaskHandle_t   task2_handler;
void task2( void * pvParameters );


/******************************************************************************************************/

List_t TestList;		 				 /* 定义测试列表 */
ListItem_t ListItem1;				  /* 定义测试列表项1 */
ListItem_t ListItem2;				/* 定义测试列表项2 */
ListItem_t ListItem3;				/* 定义测试列表项3 */		

/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
	xTaskCreate((TaskFunction_t) start_task,
							(char *)	"start_task",
							(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) START_TASK_PRIO,
							(TaskHandle_t *)&start_task_handler
	
	);
							
	//开启任务调度
	vTaskStartScheduler();
	
}
void start_task( void * pvParameters )
{
	 taskENTER_CRITICAL();               /* 进入临界区  任何任务和中断都不能打断当前程序运行*/
		xTaskCreate((TaskFunction_t) task1,
							(char *)	"task1",
							(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) TASK1_PRIO,
							(TaskHandle_t *)&task1_handler	);
							
		xTaskCreate((TaskFunction_t) task2,
							(char *)	"task2",
							(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) TASK2_PRIO,
							(TaskHandle_t *)&task2_handler	);

	vTaskDelete(NULL);//删除当前任务也就是开始任务
	taskEXIT_CRITICAL();
							
	

}

void task1( void * pvParameters )
{

		while(1)
		{
			LED0_TOGGLE();
			vTaskDelay(500);
		}
}

void task2( void * pvParameters )
{
		vListInitialise(&TestList);
		vListInitialiseItem(&ListItem1);
		vListInitialiseItem(&ListItem2);
		vListInitialiseItem(&ListItem3);
		ListItem1.xItemValue= 40;
		ListItem1.xItemValue= 50;
		ListItem1.xItemValue= 60;
		UBaseType_t i;
		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("\r\n/*****************第三步:列表项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");
		
		
		    /* 第四步:列表项2插入列表 */
    printf("\r\n/*****************第四步:列表项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");
		
		    /* 第五步:列表项3插入列表 */
    printf("\r\n/*****************第五步:列表项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");
		
		
		 /* 第六步:移除列表项2 */
    printf("\r\n/*******************第六步:移除列表项2********************/\r\n");
		i= uxListRemove( (ListItem_t * ) &ListItem2 );
		printf("当前列表剩余列表项数目%u\r\n",i);
	  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");
		
		
		    /* 第七步:列表末尾添加列表项2 */
    printf("\r\n/****************第七步:列表末尾添加列表项2****************/\r\n");
		TestList.pxIndex = &ListItem1;
		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(1000);
	}

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能的未来展望:自然语言处理(NLP)与计算机视觉(CV)

NLP和CV是人工智能的两个重要分支&#xff0c;它们在处理和分析信息方面有不同的侧重点和挑战。 NLP&#xff08;自然语言处理&#xff09;旨在让计算机理解和生成人类语言&#xff0c;主要处理的是文本信息。NLP的研究和应用主要集中在如何让计算机理解和生成人类语言&#x…

一、windows_Dos命令——批处理命令

一、批处理编程 winr输入cmd 1、打开记事本 notepad 回车 记事本保存文件要以.bat后缀进行保存 2、显示对应.bat的盘符位置 echo off 3、echo输出字符串内容 echo "hello world" 回车 4、pause等待任意键输入 win r 回车 输入cmd 回车 echo "hel…

深度学习道路提取代码跑自己的训练集(一)——CoANet代码

首先去下载作者发布在github上面的代码 为了防止我们之前的虚拟环境遭到破坏 我们首先重新克隆一个虚拟环境 conda create --name pytorch2 --clone pytorch接下来 1. 在mypath.py中定义自己的数据集 class Path(object):staticmethoddef db_root_dir(dataset):if dataset…

element el-date-picker type=“datetimerange“

刚写完结果需求变更了。封装的时间组件重新做。结合eacharts 。 直接上代码了 日期选择组件封装 <template><section class"warning-container"><header class"query-head"><el-form :inline"true" class"query-form…

【华为 ICT HCIA eNSP 习题汇总】——题目集8

1、在VRP平台下&#xff0c;关于各个协议的外部优先级的描述&#xff0c;正确的是&#xff08;&#xff09;。 A、OSPF路由的外部优先级是15 B、IS-IS路由的外部优先级是10 C、静态路由的外部优先级是60 D、BGP路由的外部优先级是20 考点&#xff1a;路由技术原理 解析&#xf…

普通相机标定——核心函数编写

准备工作 在前面的章节中我们完成了如下操作: 打开电脑摄像头采集标定图像编写基础功能函数,实现获取文件名、删除文件等操作 现在我们已经完成了标定图像的采集,如下图所示;接下来就要完成相机的内参标定了。 我们在编程实现中会调用OpenCV中的findChessbo…

Django 为应用定制化admin独立后台

定制后界面 在应用目录下找到admin.py并进行编辑 from django.contrib.admin import AdminSite from .models import Question,Choiceclass PollsAdminSite(AdminSite):site_header"Admin-site-header"site_title"admin-site-title"index_title"admi…

SpringBoot-yml文件的配置与读取

配置 值前边必须要有空格&#xff0c;作为分隔符 使用空格作为缩进表示层级关系&#xff0c;相同的层级左侧对齐 获取 使用Value(”${键名}”) 使用ConfigurationProperties(prefix "前缀") 1.前缀要与yml配置文件中的前缀一致 2.实体类的字段名与配置文件中的键名一…

[GXYCTF2019]BabySQli1

单引号闭合&#xff0c;列数为三列&#xff0c;但是没有期待的1 2 3回显&#xff0c;而是显示wrong pass。 尝试报错注入时发现过滤了圆括号&#xff0c;网上搜索似乎也没找到能绕过使用圆括号的方法&#xff0c;那么按以往爆库爆表爆字段的方法似乎无法使用了 在响应报文找到一…

拓展全球市场:静态代理IP成为跨境电商战略的关键工具

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【SpringBoot】springboot常用注解

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; SpringBoot ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 结语 我的其他博客 前言 Spring Boot作为一个轻量级、快速开发的框架&#xff0c;提供了丰富的注解来简化配置和加速开发。…

深度学习如何弄懂那些难懂的数学公式?是否需要学习数学?

经过1~2年的学习&#xff0c;我觉得还是需要数学有一定认识&#xff0c;重新捡起高等数学、概率与数理、线代等这几本&#xff0c;起码基本微分方程、求导、对数、最小损失等等还是会用到。 下面给出几个链接&#xff0c;可以用于平时充电学习。 知乎上的&#xff1a; 机器学…

你对 TypeScript 中枚举类型的理解?应用场景?

文章目录 一、是什么二、使用数字枚举字符串枚举异构枚举本质 三、应用场景参考文献 一、是什么 枚举是一个被命名的整型常数的集合&#xff0c;用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型 通俗来说&#xff0c;枚举就是一个对象的所有可能…

python环境安装sklearn及报错解决

安装 如刚开始安装&#xff0c;还未遇到问题请直接从重新安装库开始看&#xff0c;如果遇到报错&#xff0c;从问题开始看 问题 python安装sklearn报错 &#xff0c;报错信息如下 File "<stdin>", line 1pip install scikit-learn^ SyntaxError: invalid s…

【方法论】费曼学习方法

费曼学习方法是由诺贝尔物理学奖得主理查德费曼提出的一种学习方法。这种方法强调通过将所学的知识以自己的方式解释给别人来提高学习效果。 费曼学习方法的步骤如下&#xff1a; 选择一个概念&#xff1a;选择一个要学习的概念或主题。 理解和学习&#xff1a;用自己的方式学…

Redis数据结构与底层实现揭秘

在高并发的系统开发中&#xff0c;缓存和高效的数据存储机制对于提升应用性能至关重要。Redis&#xff0c;作为其中的佼佼者&#xff0c;以其卓越的性能和丰富的数据结构赢得了开发者的青睐。本文将深入探讨Redis的数据结构及其底层实现&#xff0c;带领读者走进这个高性能数据…

3ds Max宣传片怎么提升渲染速度?从硬件升级到云渲染,全面提升你的渲染速度!

在3ds Max中&#xff0c;渲染是一项耗时的任务&#xff0c;尤其是对于大型场景和复杂的动画。然而&#xff0c;通过一些优化策略和技巧&#xff0c;你可以显著加速渲染过程。以下是一些建议和技巧&#xff0c;帮助你提高3ds Max的渲染速度&#xff1a; 1.升级硬件&#xff1a; …

element+vue 之 v-limit 按钮操作权限

1.新建一个permission.js文件 import store from /storeexport default {inserted: function (el, binding) {const { perms: limits } store.state.userconst { value: params } bindingif (!limits.length) returnif (params && Array.isArray(params)) {if (!limi…

C++20 协程原理与应用

协程 要想了解协程&#xff0c;最好先搞清楚进程&#xff0c;线程&#xff0c;这样才能将三者区分开来&#xff01; 进程 vs 线程 vs 协程 进程线程协程切换者操作系统操作系统用户&#xff08;编程者&#xff09;切换时机根据操作系统自己的切换策略&#xff0c;用户不感知根…

惠友小课堂】拇外翻常见的几个误区,来看看你中了几个?

拇外翻作为常见的足部畸形&#xff0c;在日常生活中困扰着许多人。歪脚趾不仅外观不好看&#xff0c;还会出现疼痛、影响行走运动。但大多数人对于拇外翻的认识都不足常常落入认知误区&#xff0c;快来看看你中了几个&#xff1f; 误区一 Q 我都没穿过高跟鞋&#xff0c;怎么也…