当前位置: 首页 > news >正文

FreeRTOS---进阶知识1---列表的创建

在 FreeRTOS 中,列表(List) 是一种核心数据结构,用于高效管理任务、事件和其他内核对象。它本质上是一个 双向链表(Doubly Linked List)。

1. FreeRTOS 列表的特点

(1) 双向链表结构

  • 每个列表(List_t)由多个 列表项(ListItem_t 组成,列表项之间通过 前驱(pxPrevious 和 后继(pxNext 指针连接。

  • 包含一个 尾节点(xListEnd 作为哨兵节点(Sentinel Node),使遍历和插入操作更高效。

(2) 线程安全

  • FreeRTOS 列表通常用于任务调度(如就绪列表 pxReadyTasksLists),因此其操作(插入、删除、遍历)必须保证 线程安全

  • 在 SMP(多核)版本 的 FreeRTOS 中,列表可能涉及 自旋锁(Spin Lock) 保护。

(3) 支持按优先级排序

  • FreeRTOS 的任务调度依赖优先级,因此列表支持 按优先级排序,确保高优先级任务能快速被检索到。


2. FreeRTOS 列表的关键结构

(1) List_t(列表结构体)

typedef struct xLIST {volatile UBaseType_t uxNumberOfItems;  // 当前列表项数量ListItem_t *pxIndex;                   // 遍历指针(用于遍历列表)MiniListItem_t xListEnd;               // 尾节点(哨兵节点)
} List_t;
  • uxNumberOfItems:记录当前列表中的有效项数。

  • pxIndex:用于遍历列表(如 listGET_OWNER_OF_NEXT_ENTRY())。

  • xListEnd:固定尾节点,使列表操作更高效(如判断是否到达末尾)。

(2) ListItem_t(列表项结构体)


struct xLIST_ITEM {TickType_t xItemValue;             // 存储排序值(如任务优先级)struct xLIST_ITEM *pxNext;         // 指向下一个节点struct xLIST_ITEM *pxPrevious;     // 指向前一个节点void *pvOwner;                     // 指向拥有者(如任务TCB)struct xLIST *pxContainer;         // 指向所属的列表
};
  • xItemValue:用于排序(例如任务的阻塞时间或优先级)。

  • pvOwner:通常指向任务的 TCB(任务控制块)

  • pxContainer:记录该项属于哪个列表(便于快速移除)。

(3) MiniListItem_t(简化版列表项,用于尾节点)

typedef struct xMINI_LIST_ITEM {TickType_t xItemValue;            // 通常设为最大值(portMAX_DELAY)struct xLIST_ITEM *pxNext;        // 指向第一个真实节点struct xLIST_ITEM *pxPrevious;    // 指向最后一个真实节点
} MiniListItem_t;
  • 仅用于 xListEnd,不存储实际数据,仅作为列表遍历的边界。

3. 简单的链表示例

#include "usart.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct person{char *name;int age;int sex;struct person *couple;
};struct person w;
struct person h;int main(int argc, char **arg)
{HAL_Init();MX_USART1_UART_Init();w.name = 'w';w.age = 30;w.couple = &h;h.name = 'h';h.age = 30;h.couple = &w;printf ("w's couple is %s\r\n", w.couple ->name );while(1){}
}void Error_Handler(void)
{printf ("Error\r\n");while(1){}

代码运行结果如下:

4. 简单的列表示例:

#include "usart.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct person{char *name;int age;int sex;struct person *next;/*指向下一个人*/
};struct list{char *name;/*列表名称*/struct person *next;/*指向某个人*/
}int main(int argc, char **arg)
{HAL_Init();MX_USART1_UART_Init();struct list a_list;struct person p1;a_list.name = "A";a_list.next = NULL;/*空链表*/p1.name ="a1";p1.next = NULL;a_list.next = &p1;printf ("a list: %s\r\n", a_list.next ->name );while(1){}
}void Error_Handler(void)
{printf ("Error\r\n");while(1){}
  1. 数据结构定义

    • struct person:表示一个人的结构体,包含姓名、年龄、性别和指向下一个人的指针

    • struct list:表示一个链表,包含链表名称和指向第一个人的指针

  2. 主函数

    • 初始化HAL库和USART1

    • 创建一个链表a_list和一个人p1

    • p1添加到a_list

    • 打印链表中第一个人的名字

其中:

 链表头部如下:

链表项如下:

代码运行结果如下:


5. 代码实现了一个简单的链表管理系统,用于管理一组人员信息

代码如下:

#include "usart.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct person{char *name;int age;struct person *next;/*指向下一个人*/
};struct list{char *name;/*列表名称*/struct person *next;/*指向某个人*/
};void InitList(struct list *pList,char *name)
{pList ->name = name ;pList ->next = NULL ;
}void AddItemToList(struct list *pList,struct person *new_person)
{struct person *last;// 声明一个指向person结构体的指针变量last/*如果是空链表*/if (pList->next == NULL){pList->next =new_person ;new_person->next = NULL;return;}last = pList->next;while (last->next){last = last->next;}last->next = new_person;new_person->next = NULL;
}void PrintList(struct list *pList)
{int i = 0;struct person *p = pList->next ;while (p != NULL){printf("Person %d: %s is %d\r\n", i++, p->name ,p->age);/*后面还有人,移动到下一个*/p = p->next;}
}int main(int argc, char **arg)
{HAL_Init();MX_USART1_UART_Init();struct list a_list;int i;struct person p[]={{"p1",10,NULL},{"p2",20,NULL},{"p3",13,NULL},{"p4",41,NULL},{"p5",56,NULL},{"p6",12,NULL},{"p7",9,NULL},{"p8",21,NULL},{NULL ,0,NULL},};InitList(&a_list,"A_class");i = 0;while(p[i].name != NULL){AddItemToList(&a_list,&p[i]);i++;}PrintList(&a_list);while(1){}
}void Error_Handler(void)
{printf ("Error\r\n");while(1){}

代码结构

  1. 数据结构定义

    • struct person: 表示一个人,包含姓名、年龄和指向下一个人员的指针

    • struct list: 表示一个链表,包含链表名称和指向第一个人员的指针

  2. 功能函数

    • InitList(): 初始化链表

    • AddItemToList(): 向链表添加新人员

    • PrintList(): 打印链表中的所有人员信息

  3. 主程序

    • 初始化硬件和链表

    • 创建一组人员数据

    • 将人员添加到链表中

    • 打印链表内容

代码运行结果如下:

在上面的代码中,向链表末尾添加新节点,在数据结构和链表中,节点(Node) 是一个基本但非常重要的概念。

注:在链表中,尾部(Tail) 指的是链表的最后一个节点

它的特征是:

  • 指针域为NULL(next = NULL

  • 后面没有其他节点

  • 是链表遍历的终点

节点的定义

节点是数据结构中的基本单位,它包含两部分:

  1. 数据域 - 存储实际的数据

  2. 指针域 - 存储指向其他节点的地址

在上面的链表中,有两种节点:

1. 人员节点(struct person)

struct person {char *name;          // 数据域:存储姓名int age;             // 数据域:存储年龄struct person *next; // 指针域:指向下一个人员节点
};

2. 链表头节点(struct list)

struct list {char *name;           // 数据域:链表名称struct person *next;  // 指针域:指向第一个人员节点
};

节点的可视化表示

单个节点:

+---------------+
|   数据域      |  ← 存储具体信息
| (name, age)   |
+---------------+
|   指针域      |  ← 指向下一个节点
|    next       | → NULL 或其他节点
+---------------+

链表中的多个节点:

头节点             节点1               节点2               节点3
+----------+     +----------+     +----------+     +----------+
|  "A班"   |     | "张三",18|     | "李四",20|     | "王五",22|
+----------+     +----------+     +----------+     +----------+
|    ●-----|----→|    ●-----|----→|    ●-----|----→|   NULL   |
+----------+     +----------+     +----------+     +----------+

节点的作用

1. 数据存储

每个节点就像一个"容器",存储特定的数据:

  • 人员节点存储:姓名、年龄

  • 头节点存储:链表名称

2. 连接关系

通过指针域,节点之间形成连接:

// 节点1指向节点2
node1.next = &node2;// 节点2指向节点3  
node2.next = &node3;// 节点3指向NULL,表示链表结束
node3.next = NULL;

http://www.lryc.cn/news/626648.html

相关文章:

  • SQL 中大于小于号的表示方法总结
  • Claude Code NPM 包发布命令
  • 内网安全——出网协议端口探测
  • Java开源工具Apache PDFBox(强大的处理 PDF文档工具:创建、读取、修改、解析和提取 PDF)
  • Apache ShenYu和Nacos之间的通信原理
  • 【Tech Arch】Apache Pig大数据处理的高效利器
  • Spring Boot 日志体系详解:配置与实战
  • 三、k8s 1.29 之 资源清单
  • 网络编程5(HTTPS)
  • 【考研408数据结构-08】 图论基础:存储结构与遍历算法
  • Linux的奇妙冒险——进程pcb第二讲
  • 云原生俱乐部-k8s知识点归纳(5)
  • SpringTask入门
  • 关于多个el-input的自动聚焦,每输入完一个el-input,自动聚焦到下一个
  • Rust并发编程:解锁高性能系统的密钥
  • 第12课_Rust项目实战
  • 批处理指令常见问题
  • 软考高级--系统架构设计师--案例分析真题解析
  • 【clion】cmake脚本1:调试脚本并构建Fargo项目win32版本
  • 无需驱动!单文件实现键盘按键禁用的技术方案
  • 使用Jmeter轻松实现AES加密测试
  • 01-Docker概述
  • 云计算学习100天-第26天
  • FreeRTOS入门知识(任务通知(二)以及定时器浅析)(七)
  • 2025年8月技术问答第2期
  • AI 与 OCR 识别:深度融合的智能信息提取技术
  • Cobbler 自动化部署服务介绍与部署指南
  • 微服务自动注册到ShenYu网关配置详解
  • 亚矩阵:跨境卖家 YouTube 私域矩阵搭建的高效解决方案
  • 使用acme.sh自动申请AC证书,并配置自动续期,而且解决华为云支持问题,永久免费自动续期!