FreeRTOS之列表和列表项
来源:互联网 发布:手机淘宝流量劫持 编辑:程序博客网 时间:2024/06/06 04:23
列表和列表项是FreeRTOS的一个数据结构,是FreeRTOS的基石。
1.列表
列表是FreeRTOS中的一个数据结构,和链表类似,它的定义位于文件list.c和list.h中。
列表的结构体定义如下:
typedef struct xLIST{ listFIRST_LIST_INTEGRITY_CHECK_VALUE // 用来检查列表完整性:configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1时,添加一个变量,初始化列表的时候赋一个特殊的值 configLIST_VOLATILE UBaseType_t uxNumberOfItems; // 记录列表中列表项的数目 ListItem_t * configLIST_VOLATILE pxIndex; // 记录当前列表项的索引号,用于遍历列表 MiniListItem_t xListEnd; // 列表的最后一个列表项 listSECOND_LIST_INTEGRITY_CHECK_VALUE // 同listFIRST_LIST_INTEGRITY_CHECK_VALUE一样} List_t;// 宏listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE是用来检查列表完整性的。// 当宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1时,这两个地方会各添加一个变量xListIntegrityValue1和xListIntegrityValue2,初始化列表的时候,这两个变量中会写入一个特殊的值。// 默认这个功能不开启。
2.列表项
FreeRTOS提供了两种列表项:列表项和迷你列表项,它们的定义都位于文件list.h中。
(1)列表项的结构体定义如下:
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; // 记录此链表归谁拥有,也就是指向任务控制块 void * configLIST_VOLATILE pvContainer; // 用来记录此列表项归哪个列表 listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE // 用来检查列表完整性};typedef struct xLIST_ITEM ListItem_t;
(2)迷你列表项的结构体定义:
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;
3.列表初始化
列表初始化通过函数vListInitialise()来完成,此函数在文件list.c中定义,如下:
void vListInitialise( List_t * const pxList ){ // pxList此时只有一个列表项xListEnd,因此pxIndex只能指向这里 pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); // 列表是按照列表项值顺序排列的,那么xListEnd作为列表的最后一个列表项,它的列表项值应该是最大的 // portMAX_DELAY的定义位于文件portmacro.h中 pxList->xListEnd.xItemValue = portMAX_DELAY; // pxList只有xListEnd这一个列表项,因此pxNext和pxPrevious只能指向自身 pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); pxList->uxNumberOfItems = ( UBaseType_t ) 0U; // 初始化列表项中用于完整性检查字段,只有宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES为1时才有效 listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );}
4.列表项初始化
列表项的初始化由函数vListInitialiseItem()来完成,定义如下:
void vListInitialiseItem( ListItem_t * const pxItem ){ // 初始化pvContainer为NULL,保证该列表项不属于任何列表 pxItem->pvContainer = NULL; // 初始化用于完整性检查的变量,如果开启了这个功能的化 listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );}
5.列表项插入
void vListInsert( List_t * const pxList, // 列表项要插入的列表 ListItem_t * const pxNewListItem // 要插入的列表项 ){ListItem_t *pxIterator;// 获取要插入的列表项的项值,因为列表是按照列表项值升序排列的,根据这个值可以确定列表项要插入的位置const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; // 用来检查列表和列表项的完整性,其实就是检查列表和列表项中用于完整性检查的变量值是否被改变。 // configASSERT()有效时才能实现。 listTEST_LIST_INTEGRITY( pxList ); listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); // 获取要插入的点,插入的情况分两种: // 第1种:pxList的最后一个列表项xListEnd的列表项值是portMAX_DELAY,若当前要插入的列表项的项值时portMAX_DELAY的话,那么它肯定是位于列表最末尾了。 // 第2种:要插入的列表项的项值不能与portMAX_DELAY的情况,该情况需要与列表中的列表项一个一个去比较项值 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->pvContainer = ( void * ) pxList; // 列表项数目加1 ( pxList->uxNumberOfItems )++;}
注:当列表中的列表项增多时,会有一个神奇的发现:列表居然是一个环形列表。
6.列表项末尾插入
列表项末尾插入通过函数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->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious; mtCOVERAGE_TEST_DELAY(); pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem; // 记录列表项属于该列表 pxNewListItem->pvContainer = ( void * ) pxList; ( pxList->uxNumberOfItems )++;}
注:这里说的在末尾不是指xListEnd表示的末尾,而是要根据pxIndex来确定的。
7.列表项的删除
列表项的删除要通过函数uxListRemove()来实现的,定义如下:
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ){// 获取该列表项所属的列表List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; // 删除列表项 pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; mtCOVERAGE_TEST_DELAY(); // 确保pxIndex不为空 if( pxList->pxIndex == pxItemToRemove ) { pxList->pxIndex = pxItemToRemove->pxPrevious; } else { mtCOVERAGE_TEST_MARKER(); } // 清空pvContainer pxItemToRemove->pvContainer = NULL; ( pxList->uxNumberOfItems )--; // 返回列表中列表项的数目 return pxList->uxNumberOfItems;}
8.列表的遍历
将列表的遍历前,再说明一下:列表List_t中的成员变量pxIndex是用来遍历列表的。
FreeRTOS提供了一个函数来完成列表的遍历,这个函数是listGET_OWNER_OF_NEXT_ENTRY()。
每调用一次这个函数,则列表的pxIndex变量就会指向下一个项,并且返回这个列表项的pxOwner变量值,也就是TCB。
该函数本质上是一个宏,它的定义位于文件list.h文件中,如下:
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \{ \List_t * const pxConstList = ( pxList ); \ // pxIndex指向下一个列表项 ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ // 若pxIndex指向了列表的xListEnd,则跳过xListEnd,pxIndex再一次指向处于列表头的列表项 if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ { \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ } \ // 将pxIndex指向的新列表项的pvOwner赋值给pxTCB ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \}
此函数用于从多个同优先级的就绪任务中查找下一个要运行的任务。
- FreeRTOS之列表和列表项
- FreeRTOS列表和列表项
- FreeRTOS高级篇1---FreeRTOS列表和列表项
- FreeRTOS高级篇1---FreeRTOS列表和列表项
- FreeRTOS详解---列表
- FreeRTOS的列表
- 列表和列表项
- HTML学习之有序列表、无序列表和自定义列表
- python之列表和元祖
- Html之有序列表和无序列表用法_ol_li_ul_实例
- WSS3SDK之:如何添加和删除列表项
- 有序列表和无序列表
- 列表
- 列表
- 列表
- 列表
- 列表
- 列表
- error while loading shared libraries: libevent-2.1.so.6 的解决办法
- 敏感字过滤
- 【Java并发学习】之线程的同步
- /etc/inittab配置文件
- BaseRecyclerViewAdapterHelper源码解读(八) 空布局
- FreeRTOS之列表和列表项
- 无领导小组讨论如何带飞全组
- kmeans算法原理以及实践操作(多种k值确定以及如何选取初始点方法)
- java.lang.NumberFormatException: multiple points 问题
- 463. Island Perimeter (hash)
- foreach使用备份
- Unity3d protobuf-net的使用
- Vue-cli +webpack 手把手教你安装
- JPA的详解及使用方法