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

RTOS:创建队列(含源码分析)

文章目录

  • 前言
  • 一、创建队列
  • 二、详细逻辑分析
    • 2.1、参数检查
    • 2.2、内存分配
    • 2.3、初始化队列
    • 2.4、错误处理
  • 三、源码复杂度解读
    • 3.1、traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
    • 3.2、( uxQueueLength > ( UBaseType_t ) 0 )
    • 3.3、( SIZE_MAX / uxQueueLength ) >= uxItemSize )
    • 3.4、( SIZE_MAX - sizeof( Queue_t ) ) >= ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize ) )
    • 3.5、xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );
    • 3.6、pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
    • 3.7、pxNewQueue != NULL
    • 3.8、pucQueueStorage = ( uint8_t * ) pxNewQueue;
    • 3.9、pucQueueStorage += sizeof( Queue_t );
    • 3.10、pxNewQueue->ucStaticallyAllocated = pdFALSE;
    • 3.11、pxNewQueue->ucStaticallyAllocated = pdFALSE;
    • 3.12、prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
    • 3.13、return pxNewQueue;
  • 四、注意事项


前言

操作系统,在入行嵌入式j接触它之前,感觉那是多么高深、神圣的技术,感觉它是高不可攀的。曾经也幻想过它有多么的复杂,在裸机编程时无数次想去应用这个技术,但无奈,无人指引,以致于每每都会望而却步。如今,也在多种OS的基础上做过各行各业的软件开发,所以想在闲暇之时,将使用过的OS内核软件逐行阅读,以提升自我编程能力、去了解更多软件编程思想。写此专栏文章的目的也仅仅是为了让这个过程留痕。

本文所有代码源于RTOS-Keenel

一、创建队列

#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,const UBaseType_t uxItemSize,const uint8_t ucQueueType )
{Queue_t * pxNewQueue = NULL;size_t xQueueSizeInBytes;uint8_t * pucQueueStorage;traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&/* Check for multiplication overflow. */( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&/* Check for addition overflow. *//* MISRA Ref 14.3.1 [Configuration dependent invariant] *//* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-143. *//* coverity[misra_c_2012_rule_14_3_violation] */( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize ) ) ){/* Allocate enough space to hold the maximum number of items that* can be in the queue at any time.  It is valid for uxItemSize to be* zero in the case the queue is used as a semaphore. */xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );/* MISRA Ref 11.5.1 [Malloc memory assignment] *//* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 *//* coverity[misra_c_2012_rule_11_5_violation] */pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );if( pxNewQueue != NULL ){/* Jump past the queue structure to find the location of the queue* storage area. */pucQueueStorage = ( uint8_t * ) pxNewQueue;pucQueueStorage += sizeof( Queue_t );#if ( configSUPPORT_STATIC_ALLOCATION == 1 ){/* Queues can be created either statically or dynamically, so* note this task was created dynamically in case it is later* deleted. */pxNewQueue->ucStaticallyAllocated = pdFALSE;}#endif /* configSUPPORT_STATIC_ALLOCATION */prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );}else{traceQUEUE_CREATE_FAILED( ucQueueType );mtCOVERAGE_TEST_MARKER();}}else{configASSERT( pxNewQueue );mtCOVERAGE_TEST_MARKER();}traceRETURN_xQueueGenericCreate( pxNewQueue );return pxNewQueue;
}

二、详细逻辑分析

2.1、参数检查

首先检查 uxQueueLength 是否大于0、uxQueueLength 和 uxItemSize 的乘积是否会溢出。此外还检查了分配的总内存大小加上队列结构体大小是否会溢出。

2.2、内存分配

如果参数检查通过,就计算所需的总内存大小,并使用 pvPortMalloc 函数分配内存。分配的内存包括队列结构体本身和存储队列元素的存储器。

2.3、初始化队列

首先检查内存分配是否成功,当内存分配成功后,便初始化队列,包括设置队列的长度、大小、队列类型等

2.4、错误处理

如果参数检查失败或内存分配失败,函数将返回NULL,反之返回队列句柄。

三、源码复杂度解读

3.1、traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );

跟踪函数宏,调试和性能分析时用,实际应用时处于kong.

3.2、( uxQueueLength > ( UBaseType_t ) 0 )

确保 uxQueueLength 大于0。

3.3、( SIZE_MAX / uxQueueLength ) >= uxItemSize )

确保 uxQueueLength 和 uxItemSize 的乘积不会溢出。

3.4、( SIZE_MAX - sizeof( Queue_t ) ) >= ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize ) )

确保分配的总内存大小加上队列结构大小不会溢出。

3.5、xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );

计算队列存储区所需的总内存大小(字节为单位)。

3.6、pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );

为队列即将创建的队列申请内存。

3.7、pxNewQueue != NULL

判断内存申请是否成功。

3.8、pucQueueStorage = ( uint8_t * ) pxNewQueue;

记录内存申请的起始地址。

3.9、pucQueueStorage += sizeof( Queue_t );

起始地址偏移一个 Queue_t。

3.10、pxNewQueue->ucStaticallyAllocated = pdFALSE;

如果启用了静态分配支持的宏定义 configSUPPORT_STATIC_ALLOCATION ,便标记队列为动态创建。

3.11、pxNewQueue->ucStaticallyAllocated = pdFALSE;

表示队列创建为动态创建,以便后续删除。

3.12、prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );

初始化新对队列。

3.13、return pxNewQueue;

返回新队列句柄。如果创建失败便返回 NULL。

四、注意事项

  • 在使用该函数之前,需要确保FreeRTOS系统已经初始化。
  • 需要确保传入的形参值合理,以避免内存溢出。
  • 创建队列时,应考虑系统的内存限制,避免因队列过大而导致内存不足。
  • 在多任务环境中使用队列时,需要注意队列的访问冲突,FreeRTOS会自动处理这些冲突,但开发人员还需要注意。
http://www.xdnf.cn/news/12184.html

相关文章:

  • 搭建DNS域名解析服务器(正向解析资源文件)
  • 数据结构:递归:泰勒展开式(Taylor Series Expansion)
  • 如何搭建自动化测试框架?
  • simulink有无现成模块可以实现将三个分开的输入合并为一个[1*3]的行向量输出?
  • nginx 服务启动失败问题记录
  • 华新精科IPO“上会” 四大疑惑待解
  • LeetCode | 滑动窗口的原理及真题解析
  • JavaScript 数组与流程控制:从基础操作到实战应用
  • 八皇后问题深度解析
  • 05【Linux经典命令】Linux 用户管理全面指南:从基础到高级操作
  • 深入浅出工厂模式:从入门到精通(2025最新版)
  • Linux多线程
  • java教程笔记(九)-异常处理,枚举类,反射机制,注解
  • 使用 Preetham 天空模型与硬边太阳圆盘实现真实感天空渲染
  • 益莱储参加 Keysight World 2025,助力科技加速创新
  • Python正则表达式re模块
  • 资产智慧管理安全监测中心
  • 【物联网-TCP/IP】
  • 【AI学习】KV-cache和page attention
  • 【机器学习】主成分分析 (PCA)
  • AIGC图像去噪:核心原理、算法实现与深度学习模型详解
  • C++课设:智能优惠快餐点餐系统
  • 新建网站部署流程
  • glibc 交叉编译
  • Ansys Maxwell:线圈和磁体的静磁 3D 分析
  • 深度学习之模型压缩三驾马车:基于ResNet18的模型剪枝实战(1)
  • USB-C/HDMI 2.0 2:1 SW,支持4K60HZ
  • 如何选择有效的CoT提示提升模型推理性能!
  • 在历史项目升级中用SSR和SSG优化性能的实现流程
  • em/px/rem/vh/vw区别