队列实用服务

Nucleus RTOS 有四个 API 调用,它们提供与队列相关的实用功能:重置队列、返回有关队列的信息、返回应用程序中的队列数量以及返回指向应用程序中所有队列的指针。其中前三个在 Nucleus SE 中实现。

重置队列

此 API 调用将队列恢复到其初始未使用状态。存储在队列中的任何消息都将丢失。任何挂在队列上的任务都将恢复并收到NUSE_QUEUE_WAS_RESET的返回码。

用于重置队列的 Nucleus RTOS API 调用

服务调用原型:

状态 NU_Reset_Queue(NU_QUEUE *队列;

参数:

queue – 指向用户定义队列控制块的指针

返回:

NU_SUCCESS – 调用成功完成
NU_INVALID_QUEUE – 队列指针无效

用于重置队列的 Nucleus SE API 调用

此 API 调用支持 Nucleus RTOS API 的关键功能。

服务调用原型:

状态 NUSE_Queue_Reset(NUSE_QUEUE 队列);

参数:

queue – 要重置的队列的索引(ID)

返回:

NUSE_SUCCESS – 调用成功完成
NUSE_INVALID_QUEUE – 队列索引无效

队列重置的 Nucleus SE 实现

NUSE_Queue_Reset() API 函数代码的初始部分——在参数检查之后——非常简单。头尾索引和队列的消息计数都设置为零。

启用阻塞时,附加代码负责唤醒任何挂起的任务,因此:
while (NUSE_Queue_Blocking_Count[queue] != 0){ U8 索引;/* 检查是否有任务被阻塞 / / 在这个队列上 */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[ index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_QUEUE_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; 休息; } } NUSE_Queue_Blocking_Count[queue]–;}#if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK);#endif
队列中挂起的每个任务都标记为“就绪”,挂起返回代码为NUSE_QUEUE_WAS_RESET。在此过程完成后,如果优先级调度程序正在使用中,则会调用NUSE_Reschedule(),因为一个或多个更高优先级的任务可能已准备就绪并需要允许运行。

队列信息

此服务调用获取有关队列的信息选择。Nucleus SE 实现与 Nucleus RTOS 的不同之处在于它返回的信息较少,因为不支持对象命名、可变消息大小和挂起顺序,并且可能无法启用任务挂起。

Nucleus RTOS API 调用队列信息

服务调用原型:

状态 NU_Queue_Information(NU_QUEUE *queue, CHAR *name,
VOID **start_address,UNSIGNED *queue_size, UNSIGNED *available,
UNSIGNED *messages, OPTION *message_type,
UNSIGNED *message_size, OPTION suspend_type,
UNSIGNED tasks_waiting, NU_TASK);

参数:

queue – 指向用户提供的队列控制块
名称的指针 – 指向消息队列名称的 8 个字符的目标区域 的指针
start_address – 指向一个指针的指针,它将接收队列数据区域的起始地址
queue_size –一个指向保存 队列中可用UNSIGNED数据元素总数 的变量的指针 – 一个指向保存 队列中可用UNSIGNED数据元素 数量的变量的指针消息– 一个指向保存当前消息数量的变量的指针在队列message_type 中

– 指向用于保存队列支持的消息类型的变量的指针;有效的消息类型是NU_FIXED_SIZE 和NU_VARIABLE_SIZE
message_size—— 指向一个变量的指针,用于保存 每个队列消息中未签名数据元素的数量;如果队列支持可变长度消息,则此数字是最大消息大小
suspend_type – 指向用于保存任务挂起类型的变量的指针。有效的任务挂起类型是NU_FIFO 和NU_PRIORITY
tasks_waiting—— 一个指向一个变量的指针,该变量将接收这个队列中挂起的任务数量
first_task – 指向任务指针的指针;第一个挂起的任务的指针放在这个任务指针中

返回:

NU_SUCCESS – 调用成功完成
NU_INVALID_QUEUE – 队列指针无效

Nucleus SE API 调用队列信息

此 API 调用支持 Nucleus RTOS API 的关键功能。

服务调用原型:

状态 NUSE_Queue_Information(NUSE_QUEUE 队列,
ADDR *start_address,U8 *queue_size,U8 *available,U8 *messages,U8 *tasks_waiting,NUSE_TASK *first_task);

参数:

queue – 请求信息的队列索引
start_address – 指向ADDR类型变量的指针,它将接收队列数据区起始地址
queue_size – 指向U8类型变量的指针,它将接收接收队列有
可用容量的消息总数 ——一个指向U8类型变量的指针,它将接收队列当前具有剩余容量
消息的消息数 ——一个指向U8类型变量的指针,它将接收当前队列中的消息数
tasks_waiting – 一个指向一个变量的指针,该变量将接收这个队列中挂起的任务的数量(如果任务挂起被禁用,
则不返回任何内容)first_task – 一个指向NUSE_TASK类型变量的指针 ,它将接收第一个挂起任务的索引(如果禁用,则不返回任何内容)任务暂停被禁用)

返回:

NUSE_SUCCESS – 调用成功完成
NUSE_INVALID_QUEUE – 队列索引无效
NUSE_INVALID_POINTER – 一个或多个指针参数无效

队列信息的 Nucleus SE 实现

这个 API 调用的实现非常简单:
*start_address = NUSE_Queue_Data[queue];*queue_size = NUSE_Queue_Size[queue];*available = NUSE_Queue_Size[queue] - NUSE_Queue_Items[queue];*messages = NUSE_Queue_Items[queue];#if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_queue]; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 索引;for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { *first_task = index; 休息; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *第一个任务= 0;#万一

该函数返回队列状态。然后,如果启用了阻塞 API 调用,则返回等待任务的数量和第一个的索引(否则这两个参数设置为 0)。

获取队列数

此服务调用返回应用程序中配置的队列数。在 Nucleus RTOS 中,这会随时间变化,返回值将代表当前队列数,而在 Nucleus SE 中,返回值是在构建时设置的,不能更改。

Nucleus RTOS API 调用队列计数

服务调用原型:

UNSIGNED NU_Established_Queues(VOID);

参数:

没有任何

返回:

系统中创建的队列数。

Nucleus SE API 调用队列计数

此 API 调用支持 Nucleus RTOS API 的关键功能。

服务调用原型:

U8 NUSE_Queue_Count(void);

参数:

没有任何

返回:

应用中配置的队列数

队列计数的 Nucleus SE 实现

这个 API 调用的实现几乎非常简单: 返回#define 符号NUSE_QUEUE_NUMBER的值。

数据结构

队列使用五到六个数据结构 - 全部在 RAM 和 ROM 中 - 与其他 Nucleus SE 对象一样,它们是一系列表,根据配置的队列数量和选择的选项包含和确定尺寸。

我强烈建议应用程序代码不要直接访问这些数据结构,而是使用提供的 API 函数。这避免了与 Nucleus SE 未来版本的不兼容和不需要的副作用,并简化了将应用程序移植到 Nucleus RTOS 的过程。此处包含数据结构的详细信息,以便于更容易理解服务调用代码的工作和调试。

内核 RAM 数据

这些数据结构是:

NUSE_Queue_Head[] – 这是一个U8类型的数组,每个配置的队列都有一个条目,它代表一个指向消息队列前端的指针。它用作NUSE_Queue_Data[] 中地址的索引 (见下文)。

NUSE_Queue_Tail[] - 这是一个U8类型的数组,每个配置的队列都有一个条目,它代表一个指向消息队列末尾的指针。它用作NUSE_Queue_Data[] 中地址的索引 (见下文)。

NUSE_Queue_Items[] – 这是一个U8类型的数组,每个配置的队列都有一个条目,它表示队列中当前消息数的计数。这个数据可以说是多余的,因为它的值可以从头和尾索引中得出,但存储计数简化了代码。

NUSE_Queue_Blocking_Count[] – 这种类型的U8 数组包含每个队列上有多少任务被阻塞的计数。此数组仅在启用阻塞 API 调用支持时才存在。

当 Nucleus SE 启动时,这些数据结构都被NUSE_Init_Queue()初始化为零。这是合乎逻辑的,因为它将每个队列呈现为空(未使用)。以后的文章将提供 Nucleus SE 启动程序的完整说明。

以下是nuse_init.c 文件中这些数据结构的定义:
RAM U8 NUSE_Queue_Head[NUSE_QUEUE_NUMBER]; 内存 U8 NUSE_Queue_Tail[NUSE_QUEUE_NUMBER]; RAM U8 NUSE_Queue_Items[NUSE_QUEUE_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Queue_Blocking_Count[NUSE_QUEUE_NUMBER]; #万一
用户内存

用户有责任为每个配置的队列提供一个 RAM 区域用于数据存储。这个 RAM 区域的大小必须容纳一个ADDR类型的数组, 队列中的每条消息都有一个条目。

只读存储器数据

这些数据结构是:

NUSE_Queue_Data[] – 这是一个ADDR类型的数组,每个配置的队列都有一个条目,它代表每个队列的数据区(在上面的用户 RAM 中讨论过)的指针。

NUSE_Queue_Size[] – 这是一个U8类型的数组,每个配置的队列都有一个条目,表示每个队列可能容纳的消息数。

这些数据结构都在nuse_config.c 中声明和初始化(当然是静态的),因此:
ROM ADDR NUSE_Queue_Data[NUSE_QUEUE_NUMBER] ={ / 队列数据区地址------ /};ROM U8 NUSE_Queue_Size[NUSE_QUEUE_NUMBER] ={ / 队列大小------ */};

队列数据足迹

与 Nucleus SE 中的所有内核对象一样,队列所需的数据内存量很容易预测。

可以这样计算应用程序中所有队列的 ROM 数据占用空间(以字节为单位):

NUSE_QUEUE_NUMBER * (sizeof(ADDR) + 1)

当启用阻塞 API 调用时,应用程序中所有队列的内核 RAM 数据占用量(以字节为单位)可以这样计算:

NUSE_QUEUE_NUMBER * 3

否则就是:

NUSE_QUEUE_NUMBER * 4

具有索引队列的队列所需的用户 RAM 量(以字节为单位) 为:

NUSE_Queue_Size[队列] * sizeof(ADDR)

未实现的 API 调用

Nucleus RTOS 中的四个队列 API 调用未在 Nucleus SE 中实现:

创建队列

此 API 调用会创建一个队列。Nucleus SE 不需要它,因为队列是静态创建的。

服务调用原型:

状态 NU_Create_Queue(NU_QUEUE *queue, char *name,
VOID *start_address, UNSIGNED queue_size, OPTION message_type,
UNSIGNED message_size, OPTION suspend_type);

参数:

queue – 指向用户提供的队列控制块的指针;这将用作其他 API 调用中队列的“句柄”
name – 指向队列的 7 个字符的空终止名称的指针
start_address –队列的起始地址
message_type –队列支持的消息类型;可能是NU_FIXED_SIZE 或NU_VARIABLE_SIZE
message_size –如果队列支持固定大小的消息,则此参数指定每条消息的确切大小;否则,如果队列支持可变大小的消息,这是最大消息大小
suspend_type – 指定任务如何在队列上挂起。此参数的有效选项是NU_FIFO 和NU_PRIORITY,分别代表先进先出 (FIFO) 和优先级任务暂停

返回:

NU_SUCCESS—— 指示成功完成服务
NU_INVALID_QUEUE—— 指示队列控制块指针为NULL 或已在使用
NU_INVALID_MEMORY——指示start_address指定的内存区域 无效
NU_INVALID_MESSAGE——指示message_type 参数无效
NU_INVALID_SIZE——指示消息size 大于队列大小,或者队列大小或消息大小为零
NU_INVALID_SUSPEND – 表示suspend_type 参数无效

删除队列

此 API 调用会删除先前创建的队列。Nucleus SE 不需要它,因为队列是静态创建的,无法删除。

服务调用原型:

状态 NU_Delete_Queue(NU_QUEUE *队列);

参数:

queue – 指向队列控制块的指针

返回:

NU_SUCCESS—— 表示服务成功完成
NU_INVALID_QUEUE—— 表示队列指针无效

队列指针

这个 API 调用构建了一个指向系统中所有队列的指针的顺序列表。Nucleus SE 不需要它,因为队列由一个简单的索引而不是指针标识,并且它是多余的。

服务调用原型:

UNSIGNED NU_Queue_Pointers(NU_QUEUE **pointer_list,
UNSIGNED maximum_pointers);

参数:

pointer_list – 指向NU_QUEUE 指针数组的指针;该数组将填充指向系统中已建立队列的指针
maximum_pointers – 放置在数组中的最大指针数

返回:

放入数组的NU_QUEUE指针的数量

广播到队列

此 API 调用向所有等待来自指定队列的消息的任务广播一条消息。它没有用 Nucleus SE 实现,因为它会增加过多的复杂性。

服务调用原型:

状态 NU_Broadcast_To_Queue(NU_QUEUE *queue, VOID *message,
UNSIGNED size, UNSIGNED suspend);

参数:

queue – 指向队列控制块
消息的指针 – 指向广播消息
大小的指针–消息中未签名 数据元素的数量。如果队列支持变长消息,则该参数必须等于或小于队列支持的消息大小。如果队列支持固定大小的消息,这个参数必须由队列支持的消息大小完全相同的
暂停-指定是否暂停调用的任务,如果队列已满; 此参数的有效选项是NU_NO_SUSPEND、NU_SUSPEND 或超时值。

返回:

NU_SUCCESS – 指示成功完成服务
NU_INVALID_QUEUE – 指示队列指针无效
NU_INVALID_POINTER – 指示消息指针为NULL
NU_INVALID_SIZE – 指示指定的消息大小与创建队列时指定的大小不兼容
NU_INVALID_SUSPEND – 指示挂起从非任务线程
尝试 NU_QUEUE_FULL – 表示队列中没有足够的空间用于消息
NU_TIMEOUT – 表示超时到期后队列仍然已满
NU_QUEUE_DELETED – 任务暂停时队列被删除
NU_QUEUE_RESET – 任务挂起时队列被重置

与 Nucleus RTOS 的兼容性

对于 Nucleus SE 的各个方面,我的目标是尽可能保持应用程序代码与 Nucleus RTOS 的高度兼容性。队列也不例外,从用户的角度来看,它们的实现方式与 Nucleus RTOS 中的实现方式大致相同。考虑到生成的代码更易于理解,或者更有可能使内存效率更高,因此存在不兼容的领域,我认为这种不兼容是可以接受的。否则,Nucleus RTOS API 调用可能几乎直接映射到 Nucleus SE 调用。以后的文章将包含有关为 Nucleus RTOS 用户使用 Nucleus SE 的更多信息。

对象标识符

在 Nucleus RTOS 中,所有对象都由具有特定数据类型的数据结构(即控制块)描述。指向该控制块的指针用作队列的标识符。在 Nucleus SE 中,我决定需要一种不同的方法来提高内存效率,并且所有内核对象都由 RAM 和/或 ROM 中的许多表来描述。这些表的大小由配置的每个对象类型的数量决定。特定对象的标识符只是这些表的索引。所以,我已经将NUSE_QUEUE定义 为等同于U8; 这种类型的变量——而不是指针——然后用作队列标识符。这是一个小的不兼容性,如果将代码移植到 Nucleus RTOS 或从 Nucleus RTOS 移植,则很容易处理。对象标识符通常只是存储和传递,而不以任何方式进行操作。

Nucleus RTOS 还支持队列命名。这些名称仅用于基于目标的调试工具。我从 Nucleus SE 中省略了它们以节省内存。

消息大小和可变性

在 Nucleus RTOS 中,队列可以配置为处理由任意数量的未签名 数据元素组成的消息。在 Nucleus SE 中,队列被简化并且只 支持单个ADDR消息。管道在 Nucleus SE 中更加灵活,并且可以为某些应用程序提供队列的有用替代方案;管道将在本系列的下两篇文章中介绍。

Nucleus RTOS 还支持具有可变大小消息的队列,其中仅在创建时指定最大大小。Nucleus SE 不支持可变大小的消息。

队列大小

Nucleus SE 中队列中的消息数限制为 256,因为所有索引变量和常量都是U8类型。Nucleus RTOS 不受此限制。

未实现的 API 调用

Nucleus RTOS 支持十个服务调用来处理队列。其中,有四个未在 Nucleus SE 中实现。可以 在本文前面的未实现的 API 调用中找到有关这些和省略它们的决定的详细信息。
相关实战:https://www.yunduoketang.com/article/zaixianjiaoyudajian1.html
https://www.yunduoketang.com/article/zaixianjiaoyudajian1.html
https://www.yunduoketang.com/article/zaixianjiaoyudajian1.html
https://www.yunduoketang.com/article/xianshangjiaoxuext1.html
https://www.yunduoketang.com/article/xianshangjiaoxuext1.html

队列:实用服务和数据结构相关推荐

  1. 队列:实用程序服务和数据结构

    队列:实用程序服务和数据结构 Queues: utility services and data structures 队列实用程序服务 Nucleus RTOS有四个API调用,它们提供与队列相关的 ...

  2. 从“消息队列”到“服务总线”和“流处理平台”

    作者简介 Gavin,程序员.软件架构师.企业架构师,关注智能制造. 本文是专栏<智能制造系统架构>中的文章,其它文章请参阅入坑智能制造系统架构. 消息队列是分布式系统中重要的组件,也是企 ...

  3. 管道:实用程序服务和数据结构

    管道:实用程序服务和数据结构 Pipes: utility services and data structures 管道公用设施 Nucleus RTOS有四个API调用,它们提供与管道相关的实用程 ...

  4. 循环队列–C语言实现–数据结构

    循环队列–C语言实现–数据结构 目录 循环队列C语言实现数据结构 目录 一 要求 二 循环队列 三 循环队列的算法设计 1 建立循环队列 2 置空队列 3 入队 4 出队 5 打印队 四 程序 1 程 ...

  5. python线性表和队列_[笔记]python数据结构之线性表:linkedlist链表,stack栈,queue队列...

    python数据结构之线性表 python内置了很多高级数据结构,list,dict,tuple,string,set等,在使用的时候十分舒心.但是,如果从一个初学者的角度利用python学习数据结构 ...

  6. Java实现自定义队列和树结构_Java数据结构之链表、栈、队列、树的实现方法示例...

    本文实例讲述了java数据结构之链表.栈.队列.树的实现方法.分享给大家供大家参考,具体如下: 最近无意中翻到一本书,闲来无事写几行代码,实现几种常用的数据结构,以备后查. 一.线性表(链表) 1.节 ...

  7. c语言编写队列元素逆置,数据结构与算法实验—利用栈逆置队列元素.doc

    数据结构与算法实验-利用栈逆置队列元素 利用栈逆置队列元素实验报告 通信1204班 谢崇赟 实验名称 利用堆栈将队列中的元素逆置 实验目的 会定义顺序栈和链栈的结点类型. 掌握栈的插入和删除结点在操作 ...

  8. c++数据结构队列栈尸体_数据结构-第三章:栈和队列(栈的应用、括号匹配、表达式转换)...

    第三章:栈和队列 下面讲解栈的应用主要内容有:栈的应用.括号匹配.中 后 前 缀表达式转换 1.栈的应用 1.1括号匹配 我们在数学运算中 [(A+b)*c] - (E-F) 往往都会有[ ] 和 ( ...

  9. 环形队列的输出_Java数据结构:使用数组实现环形队列详解

    队列 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除 ...

  10. 宝塔部署Yii框架多个商城项目,队列问题“服务测试失败,请检查服务是否正常运行”

    原因:队列起了相同的编号,导致运行队列冲突 Centos7.8 多个商城在同一个宝塔内,必须要设置\config\local.php,给不同队列起不同编号,那么多个商城运行队列不冲突 'queue' ...

最新文章

  1. Sass (Syntactically Awesome StyleSheets)
  2. java原生类型没有封装_Java基本数据类型与封装类型详解(int和Integer区别)
  3. 云计算服务在小企业中的意义如何?
  4. go io.reader 多次读取_Go 经典入门系列 24:Select
  5. python实现rpc框架_使用Python实现RPC框架
  6. 当学术大家遇到技术大拿,如何攻克数据库应用头号难题?数位产学研大咖这样解读
  7. LeetCode38.报数
  8. 【转】JavaScript中的this关键字使用的四种调用模式
  9. 做添加页面判断用户是否全部填写输入框
  10. 软件工程实验报告二软件可行性分析报告编写
  11. 2021年上半年软件设计师下午真题及答案解析
  12. 360无线网怎么没有网络连接到服务器,360路由器设置成二级路由器教程 | 192路由网...
  13. 一种屏蔽win10指定更新补丁的设置方法
  14. web页面:浏览器操作
  15. App测试中IOS和安卓测试的区别
  16. 视频抽帧为图片和一系列图片转换为视频
  17. java 内存 回收_java内存回收
  18. REW声学测试(四):REW的测试原理
  19. Oracle设计简单的图书管理
  20. ITGO重装上阵、谁与争锋

热门文章

  1. 什么是CBR,VBV,CPB
  2. POI导出换行和水平居中
  3. Android防止启动页面闪白问题
  4. 《摄影测量学》空间后方交会详细解读
  5. 對Googgle adsense廣告作弊和Googeladsense點擊廣告的生存前景看法
  6. java case 字符_Java中Switch Case使用字符串
  7. php studay,studay是什么意思
  8. ESP8266驱动RDA5807实现的FM收音机,可连接WiFi显示B站粉丝数
  9. CAD2014安装一整套流程
  10. psd转html 织梦,如何将PSD模型转化成XHTML和CSS文件