FreeRTOS数据结构(一)--链表和链表项
结构体定义
/*链表结构体*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/
configLIST_VOLATILE UBaseType_t uxNumberOfItems; /*记录链表项数目*/
ListItem_t * configLIST_VOLATILE pxIndex; /*用于遍历链表,初始化会指向最后的链表项,这里需要注意使用了volatile关键字,表明该指针可能会在其他地方修改*/
MiniListItem_t xListEnd;/*用于标记链表尾*/
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/
} List_t;
/*链表项结构体*/
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 /*用于链表完整性检查*/
};
/*迷你链表项结构体*/
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;
};
根据定义可以看出以下几点:
- 链表结构是一个双向链表。
- 每个链表都由链表和链表项组成。
- 链表结构体本身有一个迷你链表项,用来标记链表的结尾。
链表和链表项初始化
/*链表初始化*/
void vListInitialise( List_t * const pxList )
{
/*将链表的Index索引指针指向自身的迷你链表项,即链表结尾*/
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 );
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/*初始化链表的完整性检查值*/
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
/*链表项初始化*/
void vListInitialiseItem( ListItem_t * const pxItem )
{
/*确保该链表项没有被链表使用,往往初始化链表项之后就会进行插入或设置操作*/
pxItem->pvContainer = NULL;
/*初始化完整性检查*/
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
链表的操作
链表的插入会根据List Item Value进行升序排列,其他并没有什么特殊的地方。初始化并插入两个节点后大概的数据结构,如下图所示:

从图中可以看出,List初始化并添加节点后,List Item 1/List Item 2 和 List自己的xListEnd节点一起组成了一个双向循环的链表。
Q&A
1).如何完成链表的完整性检查?
如果打开了完整性检查的开关(configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES),每个链表和链表项结构都会定义listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE(mini链表项没有定义这个),该定义是一个16位或32位的整形数,在链表或链表项初始化的时候会将该变量初始化为0x5a5a或0x5a5a5a5a,在检查的时候如果这两个变量都没有改变则通过完整性检查,否则认为链表被破坏。
2).如何使用List?
- 必须先定义一个List_t的全局变量,比如Timer中的 xActiveTimerList1
- 每一个节点结构体必须包含xLIST_ITEM类型的成员。
- 初始化链表后,将含有List Item成员的数据结构按照链表项值的大小插入到链表中,比如Timer中利用该值溢出的判断。
- 设置好pvOwner指针,后续可以根据该指针反向找到该节点的具体结构,如Timer_t。
FreeRTOS数据结构(一)--链表和链表项的更多相关文章
- js数据结构与算法--单链表的实现与应用思考
链表是动态的数据结构,它的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 现实中,有一些链表的例子. 第一个就是寻宝的游戏.你有一条线索,这条线索是指向寻找下一条线 ...
- JavaScript 数据结构与算法3(链表)
学习数据结构的 git 代码地址: https://gitee.com/zhangning187/js-data-structure-study 1.链表 本章学习如何实现和使用链表这种动态的数据结构 ...
- 数据结构——基于java的链表实现(真正理解链表这种数据结构)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10759599.html,否则将追究法律责任!!! 一.链表介绍 1.什么是链表? 链表是一 ...
- 自己动手实现java数据结构(二) 链表
1.链表介绍 前面我们已经介绍了向量,向量是基于数组进行数据存储的线性表.今天,要介绍的是线性表的另一种实现方式---链表. 链表和向量都是线性表,从使用者的角度上依然被视为一个线性的列表结构.但是, ...
- php数据结构课程---2、链表(php中 是如何实现单链表的(也就是php中如何实现对象引用的))
php数据结构课程---2.链表(php中 是如何实现单链表的(也就是php中如何实现对象引用的)) 一.总结 一句话总结: php是弱类型语言,变量即可表示数值,也可表示对象:链表节点的数据域的值就 ...
- C# 数据结构 - 单链表 双链表 环形链表
链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一 ...
- jdk1.8HashMap底层数据结构:散列表+链表+红黑树,jdk1.8HashMap数据结构图解+源码说明
一.前言 本文由jdk1.8源码整理而得,附自制jdk1.8底层数据结构图,并截取部分源码加以说明结构关系. 二.jdk1.8 HashMap底层数据结构图 三.源码 1.散列表(Hash table ...
- 数据结构:DHUOJ 删除链表的顺数及倒数第N个节点
删除链表的顺数及倒数第N个节点 作者: turbo时间限制: 1S章节: DS:数组和链表 题目描述: 可使用以下代码,完成其中的removeNth函数,其中形参head指向无头结点单链表,n为要删除 ...
- 数据结构与算法之PHP实现链表类(单链表/双链表/循环链表)
链表是由一组节点组成的集合.每个节点都使用一个对象的引用指向它的后继.指向另一个节点的引用叫做链表. 链表分为单链表.双链表.循环链表. 一.单链表 插入:链表中插入一个节点的效率很高.向链表中插 ...
随机推荐
- wince6.0 编译报错:"error C2220: warning treated as error - no 'object' file generated"的解决办法
内容提要:wince6.0编译报错:"error C2220: warning treated as error - no 'object' file generated" 原因是 ...
- 数据结构---栈C语言实现
#include <stdio.h> #include <stdlib.h> #define uchar unsigned char #define uint unsigned ...
- 安卓系统底层C语言算法之测试参数是几个long型的算法
#include <stdio.h> #define BITS_PER_LONG (sizeof(unsigned long) * 8) //求一个数x是几个long的长度 #define ...
- 【Nginx】下载,请求限速,根据URL参数限速
这个场景是限制单个连接的下载速度,还有限制单个IP的连接数,或者单位时间内的请求数,实验环境 nginx1.9.x. 小例子为主,具体的细节请多看文档. 限制下载速度 location /downlo ...
- GNU中的处理目标文件的若干工具
AR 创建静态库,插入.删除.列出和提取成员: SRING 列出目标文件中的字符串: SIRIP 从目标文件中删除符号表信息: NM 列出目标文件符号表中定义的符号: SIZE 列出目标文件中节的名字 ...
- Django处理流程
用户通过浏览器发送请求 请求到达request中间件,中间件对request请求做预处理或者直接返回response 若未返回response,会到达urlconf路由,找到对应视图函数 视图函数做相 ...
- InnoDB的4个特性
innodb 的四个特性 insert buffer innodb使用insert buffer"欺骗"数据库:对于为非唯一索引,辅助索引的修改操作并非实时更新索引的叶子页,而是把 ...
- JavaScript数组中出现的次数最多的元素
var arr = [1,-1,2,4,5,5,6,7,5,8,6]; var maxVal = arr[0]; // 数组中的最大值 var minVal = arr[0]; // 数组中的最小值 ...
- Angularjs Post传值后台收不到的原因
如果你给AngularJS的post方法的data参数创一个key-value对象,那传给后台服务的就是JSON字符串,而正常的POST解析是需要像get?后面的那种&name=value这样 ...
- 使用Navicat连接阿里云服务器上的MySQL数据库--转
手把手教你如何正确连接阿里云服务器上的数据库: 1.首先打开Navicat,文件>新建连接>MySQL连接,其他的如一图所示. 2.因为是连接服务器上的MySQL,所以我们使用SSH连接, ...