FreeRTOS学习——链表list

FreeRTOS学习——链表(列表)list,仅用于记录自己阅读与学习源码

FreeRTOS Kernel V10.5.1

参考大佬的好文章:
freertos内核原理 Day1(链表)
FreeRTOS-链表的源码解析

*list_t只能存储指向list_item_t的指针。每个list_item_t都包含一个数值(xItemValue)。大多数时候,列表是按项目值升序排列的。

*创建的列表已包含一个列表项。此项的值是可以存储的最大值,因此它始终位于列表的末尾,并充当标记。列表成员pxHead始终指向此标记,即使它位于列表的末尾。这是因为尾部包含一个返回指针,指向列表的真正头部。

*除了它的值外,每个列表项还包含一个指向列表中下一个项的指针(pxNext)、一个指向它所在列表的指针(pxContainer)和一个指向包含它的对象的指针。为了提高列表操作的效率,包含了后两个指针。包含列表项的对象和列表项本身之间实际上存在双向链接。

链表结构体

关于链表的结构体,有三个,分别是

1. 节点结构体
2. 尾节点结构体(mini节点)
3. 链表结构体

可以看大佬的博客freertos内核原理 Day1(链表),非常清晰

节点结构体 ListItem_t

/** 列表可以包含的唯一对象类型的定义*/
struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< 链表节点完整性检查值1 */configLIST_VOLATILE TickType_t xItemValue;          /*< 链表节点值,用于阻塞升序排序 */struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*< 指向链表中的下一个节点 */struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< 指向链表中的上一个节点 */void * pvOwner;                                     /*< 指向拥有该链表节点的对象 (一般是TCB) . */struct xLIST * configLIST_VOLATILE pxContainer;     /*< 指向节点所在的链表. */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*< 链表节点完整性检查值2. */
};
typedef struct xLIST_ITEM ListItem_t;

若宏configLIST_VOLATILE定义为空,且若完整性检查宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES也为0的话(见下面关于链表宏部分),那么这个链表节点结构体其实就长这个样子,一下子干净多了。

struct xLIST_ITEM
{TickType_t xItemValue;          /*< 链表节点值,用于阻塞升序排序 */struct xLIST_ITEM * pxNext;     /*< 指向链表中的下一个节点 */struct xLIST_ITEM * pxPrevious; /*< 指向链表中的上一个节点 */void * pvOwner;                 /*< 指向拥有该链表节点的对象 (一般是TCB) . */struct xLIST * pxContainer;     /*< 指向节点所在的链表. */
};
typedef struct xLIST_ITEM ListItem_t;

链表节点值TickType_t xItemValue;为什么是TickType_t 类型呢,阻塞时间就是多少个TickType_t ,这个值用于插入延迟列表时,将节点从低到高的排列,阻塞时间段的在最前面,只要前面的没有唤醒,那么后面的也一定在阻塞,因为是升序排列的。

尾节点结构体(mini节点) MiniListItem_t

#if ( configUSE_MINI_LIST_ITEM == 1 )struct xMINI_LIST_ITEM{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< 链表节点完整性检查值1 */configLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;};typedef struct xMINI_LIST_ITEM MiniListItem_t;
#elsetypedef struct xLIST_ITEM      MiniListItem_t;
#endif

如果宏configUSE_MINI_LIST_ITEM 为1 ,则定义xMINI_LIST_ITEM 为MiniListItem_t,否则就把普通节点xLIST_ITEM定义为尾节点。

与普通节点相比,尾节点结构体少了pvOwner和pxContainer

链表结构体(根节点) List_t

/** 调度器使用的队列类型的定义*/
typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE      /*< 链表完整性检查值1 */volatile UBaseType_t uxNumberOfItems;ListItem_t * configLIST_VOLATILE pxIndex; /*< 索引指针,通过调用listGET_OWNER_OF_NEXT_ENTRY ()来遍历链表的指针 */MiniListItem_t xListEnd;                  /*< 尾节点拥有最大的xItemValue值. */listSECOND_LIST_INTEGRITY_CHECK_VALUE     /*< 链表完整性检查值2 */
} List_t;

注意,尾节点结构体MiniListItem_t 和链表结构体List_t并不是链表连接起来的,而是MiniListItem_t 是List_t的一部分,可以把List_t想象成一个大东西,而这个大东西 在链表的尾部,也可以说在头尾,因为是双向链表。List_t通过MiniListItem_t 链接起整个链表,只要获取了List_t,就能一节一节的获取整个链表,List_t也可以叫做根节点。

链表操作

初始化链表 vListInitialise

void vListInitialise( List_t * const pxList )
{/* 将索引指针指向尾节点 */pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*尾节点xListEnd使用mini节点结构体,节省RAM *//*给尾节点完整性检查值 赋值,尾节点只有一个完整性检查值 */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );/* 尾节点值为最大值0xffffffffUL,确保其为最后一个节点*/pxList->xListEnd.xItemValue = portMAX_DELAY;/* 当链表为空时,尾节点的前后指针指向尾节点自己 */pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );     pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /* 如果尾节点没有使用mini节点结构体,则初始化其pvOwner和pxContainer指针 */#if ( configUSE_MINI_LIST_ITEM == 0 ){pxList->xListEnd.pvOwner = NULL;pxList->xListEnd.pxContainer = NULL;listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );}#endif/*节点数量为0*/pxList->uxNumberOfItems = ( UBaseType_t ) 0U;/* 给链表完整性检查值 赋值 */listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
  1. 链表索引指针指向尾节点
  2. 尾节点值设为最大值,且前后指针都指向自己
  3. 节点数量为0

初始化链表节点 vListInitialiseItem

void vListInitialiseItem( ListItem_t * const pxItem )
{/* pxContainer指该节点属于哪个链表,初始值为NULL,确保该节点没有在任何链表中. */pxItem->pxContainer = NULL;/* 给节点完整性检查值 赋值. */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

链表尾部插入节点 vListInsertEnd

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 插入到 pxIndex 之前  */pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious = pxIndex->pxPrevious;/* 覆盖率测试,不影响功能,仅用于覆盖率测试 */mtCOVERAGE_TEST_DELAY();pxIndex->pxPrevious->pxNext = pxNewListItem;pxIndex->pxPrevious = pxNewListItem;/* 将节点的pxContainer指针指向链表 */pxNewListItem->pxContainer = pxList;/*链表节点数量加1*/( pxList->uxNumberOfItems )++;
}
  1. 将新节点 pxNewListItem 插入到 pxIndex 之前
  2. 将节点的pxContainer指针指向链表
  3. 链表节点数量加1

链表插入节点 vListInsert

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 );/* 将新的列表项插入列表,按xItemValue顺序排序* 如果节点值是最大值,则插入到尾节点之前*/if( xValueOfInsertion == portMAX_DELAY ){pxIterator = pxList->xListEnd.pxPrevious;}else{/* *** NOTE ************************************************************  如果程序崩溃,可能原因如下:**   1) 栈溢出*   2) 优先级分配错误*   3) 从关键部分或当调度程序暂停时调用API函数,或从中断调用不以“FromISR”结尾的API函数*   4) 在队列或信号量初始化之前 或 调度程序启动之前使用它(中断是在vTaskStartScheduler()被调用之前触发的吗?)*   5) 果FreeRTOS端口支持中断嵌套,则确保滴答中断的优先级等于或低于configMAX_SYSCALLINTERRUPT_priority**********************************************************************/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;/* 将新节点的pxContainer指针指向链表 */pxNewListItem->pxContainer = pxList;/*链表节点数量加1*/( pxList->uxNumberOfItems )++;
}
  1. 确认要插入的位置,如果节点值是最大值,则插入到尾节点之前,否则遍历链表
  2. 插入新节点
  3. 将新节点的pxContainer指针指向链表
  4. 链表节点数量加1

从链表移除节点 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();}/* 将节点的pxContainer指针指向NULL */pxItemToRemove->pxContainer = NULL;/*链表节点数量减 1*/( pxList->uxNumberOfItems )--;/*返回链表中剩余节点数量*/return pxList->uxNumberOfItems;
}
  1. 将节点从链表中移除
  2. 将节点的pxContainer指针指向NULL
  3. 链表节点数量减 1并返回链表中剩余节点数量

链表宏

configLIST_VOLATILE

*列表结构成员是在中断内修改的,因此应该声明为volatile。然而,它们只能以功能原子的方式进行修改(在调度器挂起的关键部分内),并且要么通过引用传递到函数中,要么通过volatile变量进行索引。因此,在迄今为止测试的所有用例中,可以省略volatile限定符,以便在不影响功能行为的情况下提供适度的性能改进。IAR、ARM和GCC编译器在为最大优化设置相应编译器选项时生成的汇编指令已经过检查,并被认为符合预期。也就是说,随着编译器技术的进步,特别是如果使用了激进的跨模块优化(一个没有得到很大程度应用的用例),那么正确的优化就可能需要volatile限定符。预计编译器会删除基本代码,因为如果列表结构成员上没有volatile限定符,并且进行了积极的跨模块优化,编译器认为代码是不必要的,这将导致调度器完全和明显的失败。如果遇到这种情况,那么只需在FreeRTOSConfig.h中将configLIST_volatile定义为volatile,就可以将volatile限定符插入列表结构中的相关位置(如本注释块底部的示例所示)。如果未定义configLIST_VOLATILE,则下面的预处理器指令将完全#define configLIST_VOLATILE。

*要使用volatile列表结构成员,请在FreeRTOSConfig.h中添加以下行(不带引号):“#define configLIST_volatile volatile”

#ifndef configLIST_VOLATILE#define configLIST_VOLATILE
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */

简单点说就是在迄今为止测试的所有用例中,可以省略volatile。但是如果使用了激进的跨模块优化,就可能需要volatile限定符,那么就在FreeRTOSConfig.h中添加:“#define configLIST_volatile volatile”。

现在configLIST_VOLATILE是定义为空的,因为volatile可以省略。

configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES

可用于在列表结构中放置已知值的宏,然后检查已知值在应用程序执行过程中是否损坏。这些可能会捕获内存中被覆盖的列表数据结构。它们不会捕获因FreeRTOS配置或使用不正确而导致的数据错误
在这里插入图片描述
在FreeRTOS中,这段宏定义与列表数据完整性检查相关。具体来说,它们的作用是根据configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES宏的值决定是否启用数据完整性检查功能。
(默认为0,即不开启)

当configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES被设置为0时,这段代码通过定义一系列宏为空操作(即不执行任何操作),来关闭列表数据的完整性检查功能。这意味着在使用列表数据结构时,系统不会进行额外的完整性校验,这样可以降低运行时的开销,适用于对性能要求较高的场景。

这些宏的具体定义如下:

*listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE :列表节点完整检查值1
*listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE:列表节点完整检查值2。
这两个用于表示列表节点完整性检查的值,若不启用则为空。若启用了会在列表节点结构体中添加
TickType_t xListItemIntegrityValue1;
和TickType_t xListItemIntegrityValue2;

*listFIRST_LIST_INTEGRITY_CHECK_VALUE :列表完整检查值1
*listSECOND_LIST_INTEGRITY_CHECK_VALUE:列表完整检查值2
同上面两个值类似,用于表示整个列表的完整性检查值,同样不启用时为空。

*listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem):赋值列表节点完整性检查值1
*listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem):
它会赋值列表节点中的xListItemIntegrityValue为定义的值#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL

*listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList) :赋值列表完整性检查值1
*listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList):
同上面两个值类似

*listTEST_LIST_ITEM_INTEGRITY(pxItem):用于测试列表节点的完整性
*listTEST_LIST_INTEGRITY(pxList):用于测试整个列表的完整性
上面的宏不是已经幅过值了吗,那么这两个宏就是检查上面的值有没有发生变化

总之,这些宏确保在不需要数据完整性检查时,代码的执行不会受影响,从而提高系统的性能。同时,若需要进行完整性检查(即configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为非零值),这些宏可以被重新定义,以执行必要的检查逻辑。这样的设计使得FreeRTOS能够灵活地在不同的应用场景中进行配置。

listGET_OWNER_OF_NEXT_ENTRY

/** 链表成员pxIndex用于遍历列表* 调用listGET_OWNER_OF_NEXT_ENTRY会将pxIndex递增到列表中的下一个节点,并返回该节点的拥有者pxOwner(一般是TCB)。* 因此,通过多次调用此函数,可以遍历列表中包含的每个项目。* 列表项的pxOwner参数是指向拥有该列表项的对象的指针。在调度器中,这通常是一个任务控制块。*/
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                           \{                                                                                          \List_t * const pxConstList = ( pxList );                                               \/* 链表索引pxIndex指向下一个节点*/               \/* 确保不返回尾节点  */                         \( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                           \if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \{                                                                                      \( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                       \}                                                                                      \( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                         \}

listREMOVE_ITEM

/** 删除节点* 不返回值的uxListRemove()的版本。通过内联对xTaskIncrementTick()进行了轻微优化*/
#define listREMOVE_ITEM( pxItemToRemove ) \{                                     \/* 获取节点所在的链表 */                                                              \List_t * const pxList = ( pxItemToRemove )->pxContainer;                 \\( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext;     \/* 确保索引指针指向正确的节点 */              \if( pxList->pxIndex == ( pxItemToRemove ) )                              \{                                                                        \pxList->pxIndex = ( pxItemToRemove )->pxPrevious;                    \}                                                                        \\( pxItemToRemove )->pxContainer = NULL;                                  \( pxList->uxNumberOfItems )--;                                           \}

listINSERT_END

/** 内联版本vListInsertEnd()对xTaskIncrementTick()进行了轻微优化.** 通过多次调用listGET_OWNER_OF_NEXT_ENTRY.确保插入的节点位于最后一个节点** 列表成员pxIndex用于遍历列表,调用listGET_OWNER_OF_NEXT_ENTRY会将pxIndex递增到列表中的下一个节点。* 使用vListInsertEnd将节点有效地放置在pxIndex指向的列表位置。* 这意味着在pxIndex参数再次指向要插入的项之前,列表中的所有其他项都将由listGET_OWNER_OF_NEXT_ENTRY返回。*/
#define listINSERT_END( pxList, pxNewListItem )           \{                                                     \ListItem_t * const pxIndex = ( pxList )->pxIndex; \\/* 链表完整性检查 */                                 \listTEST_LIST_INTEGRITY( ( pxList ) );                                  \listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) );                      \\/* 通过调用listGET_OWNER_OF_NEXT_ENTRY(). 确保插入的节点位于最后一个节点*/     \( pxNewListItem )->pxNext = pxIndex;                 \( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \\pxIndex->pxPrevious->pxNext = ( pxNewListItem );     \pxIndex->pxPrevious = ( pxNewListItem );             \\/* 将节点的pxContainer指针指向链表 */                    \( pxNewListItem )->pxContainer = ( pxList );         \\( ( pxList )->uxNumberOfItems )++;                   \}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware vCenter Server 7.0U3s 发布下载,新增功能概览

VMware vCenter Server 7.0U3s 下载 - 集中管理 vSphere 环境 Server Management Software | vCenter | 集中管理 vSphere 环境 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vcenter-7-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者…

YOLO交通目标识别数据集(红绿灯-汽车-自行车-卡车等)

YOLO交通目标识别 数据集 模型 ui界面 ✓图片数量15000&#xff0c;xml和txt标签都有&#xff1b; ✓class&#xff1a;biker&#xff0c;car&#xff0c;pedestrian&#xff0c;trafficLight&#xff0c;trafficLight-Green&#xff0c;trafficLight-GreenLeft&#xff0c; t…

2024年度国自然基金初审不受理的十大原因

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 2024年度基金申请已落下帷幕。近日&#xff0c;《中国科学基金》刊登了国自然基金委工作人员总结的2024年度国自然项目分析。一起来看下&#xff0c;为来年再战做准备。 …

【Docker】安装全流程与配置完整镜像源(可安装 nginx)

目录 一、卸载历史版本&#xff08;选&#xff09;二、配置 yum 源三、安装 docker四、配置 docker 镜像源加速&#xff08;选、强烈建议&#xff09;4.1 配置阿里镜像加速4.2 配置其他镜像源 五、启动 docker参考文章与视频 本文基于 Linux - CentOS 7 操作系统。 一、卸载历史…

面试真题:谈一谈Mysql的分库分表

分表和分库是什么&#xff1f;有什么区别&#xff1f; 分库是一种水平扩展数据库的技术&#xff0c;将数据根据一定规则划分到多个独立的数据库中。每个数据库只负责存储部分数据&#xff0c;实现了数据的拆分和分布式存储。分库主要是为了解决并发连接过多&#xff0c;单机 my…

【2024】前端学习笔记7-颜色-位置-字体设置

学习笔记 1.定义&#xff1a;css2.颜色&#xff1a;color3.字体相关属性&#xff1a;font3.1.字体大小&#xff1a;font-size3.2.字体风格&#xff1a;font - style3.3.字体粗细&#xff1a;font - weight3.4.字体族&#xff1a;font - family 4.位置&#xff1a;text-align 1.…

uniapp快速入门教程,内容来源于官方文档,仅仅记录快速入门需要了解到的知识点

uniapp快速入门教程&#xff0c;内容来源于官方文档&#xff0c;仅仅记录快速入门需要了解到的知识点 目录 介绍uniapp 介绍uniapp x 介绍功能框架图创建项目&发布组件/标签的变化js的变化css的变化工程结构和页面管理 pages.jsonmanifest.json 应用配置组件easycom组件规…

QT For Android开发-打开PPT文件

一、前言 需求&#xff1a; Qt开发Android程序过程中&#xff0c;点击按钮就打开一个PPT文件。 Qt在Windows上要打开PPT文件或者其他文件很容易。可以使用QDesktopServices打开文件&#xff0c;非常方便。QDesktopServices提供了静态接口调用系统级别的功能。 这里用的QDesk…

Isaac Sim 4.2.0 Windows版本打开报 fbgemm.dll 加载错误

方案一&#xff1a;下载缺少的dll复制到目录里即可 可以看到后台命令窗口出现了错误&#xff0c;发生在import pytorch的时候&#xff0c;根据提示&#xff0c;是因为fbgemm.dll缺少依赖&#xff0c;导致加载异常&#xff0c;一般情况是缺少 libomp140.x86_64.dll 这个文件&am…

【BEV 视图变换】Ray-based(2): 代码复现+画图解释 基于深度估计、bev_pool(代码一键运行)

paper&#xff1a;Lift, Splat, Shoot: Encoding Images from Arbitrary Camera Rigs by Implicitly Unprojecting to 3D code&#xff1a;https://github.com/nv-tlabs/lift-splat-shoot 一、完整复现代码(可一键运行)和效果图 import torch import torch.nn as nn import mat…

数模方法论-整数规划

一、基本概念 非线性规划的应用包括工程设计、资源分配、经济模型等。在求解过程中&#xff0c;由于非线性特性&#xff0c;常用的方法有梯度法、牛顿法、启发式算法等。求解非线性规划问题时&#xff0c;解的存在性和唯一性通常较难保证&#xff0c;且可能存在多个局部最优解…

《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易)

目录 一、最终实现后&#xff0c;效果如下。 &#xff08;1&#xff09;简单介绍本游戏项目&#xff08;待完善&#xff09; &#xff08;2&#xff09;运行效果图&#xff08;具体大家自己可以试&#xff09; 初始运行情况。 手动更换背景图。 通过子弹攻击敌机&#xff0c;累…

Echats 实现CPK (过程能力)研究报告

背景: 实现: Echarts Option 代码示例 option {title: {text: 折线图示例 - X轴为数值},xAxis: {type: value, // X 轴改为数值型min: 0, // 最小值max: 10, // 最大值},yAxis: {type: value},series: [{type: line,data: [[0, 150], [2, 230], [4, 224], [6…

嵌入式单片机STM32开发板详细制作过程--01

大家好,今天主要给大家分享一下,单片机开发板的制作过程,原理图的制作与PCB设计,以及电子元器件采购与焊接。 第一:单片机开发板成品展示 板子正面都有各个芯片的丝印与标号,方便焊接元器件的时候,可以参考。(焊接完成之后,成品图如下) 第二:开发板原理图制作 在制…

FLStudio21Mac版flstudio v21.2.1.3430简体中文版下载(含Win/Mac)

给大家介绍了许多FL21版本&#xff0c;今天给大家介绍一款FL Studio21Mac版本&#xff0c;如果是Mac电脑的朋友请千万不要错过&#xff0c;当然我也不会忽略掉Win系统的FL&#xff0c;链接我会放在文章&#xff0c;供大家下载与分享&#xff0c;如果有其他问题&#xff0c;欢迎…

Spring后端直接用枚举类接收参数,自定义通用枚举类反序列化器

在使用枚举类做参数时&#xff0c;一般会让前端传数字&#xff0c;后端将数字转为枚举类&#xff0c;当枚举类很多时&#xff0c;很可能不知道这个code该对应哪个枚举类。能不能后端直接使用枚举类接收参数呢&#xff0c;可以&#xff0c;但是受限。 Spring反序列默认使用的是J…

投资学 01 定义,投资

02. 03. 3.1 直接投资&#xff1a;使用方和提供方是一个人

yolov8模型在Xray图像中关键点检测识别中的应用【代码+数据集+python环境+GUI系统】

yolov8模型在X yolov8模型在Xray图像中关键点检测识别中的应用【代码数据集python环境GUI系统】 1.背景意义 X射线是一种波长极短、穿透能力极强的电磁波。当X射线穿透物体时&#xff0c;不同密度和厚度的物质会吸收不同程度的X射线&#xff0c;从而在接收端产生不同强度的信号…

WordPress建站钩子函数及使用

目录 前言&#xff1a; 使用场景&#xff1a; 一、常用的wordpress钩子&#xff08;动作钩子、过滤器钩子&#xff09; 1、动作钩子&#xff08;Action Hooks&#xff09; 2、过滤器钩子&#xff08;Filter Hooks&#xff09; 二、常用钩子示例 1、添加自定义 CSS 和 JS…

实战OpenCV之直方图

基础入门 直方图是对数据分布情况的图形表示&#xff0c;特别适用于图像处理领域。在图像处理中&#xff0c;直方图通常用于表示图像中像素值的分布情况。直方图由一系列矩形条&#xff08;也被称为bin&#xff09;组成&#xff0c;每个矩形条的高度表示某个像素值&#xff08;…