OpenHarmony——内核对象队列之算法详解(下)

【OpenHarmony】内核通信(消息队列) 在/home/openharmony/device/qemu/arm_mps2_an386/liteos_m/board路径下的main.c文件中进行修改在/home/openharmony/kernel/liteos_m/components/shell路径下的BUILD.gn中添加用户命令在/home/openharmony/kernel/liteos_m/components/shell/src/cmds路径下添加用户命令源文件my_shellcmd.c(void)argc; 阅读详情

前言

OpenAtom OpenHarmony(以下简称“OpenHarmony”) LiteOS-M 内核是面向 IoT 领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。在嵌入式领域的开发工作中,无论是自研还是移植系统,均绕不开内核,开发者只有掌握内核的相关知识,才能更好地深耕物联网产品领域。OpenHarmony LiteOS-M内核对象队列的算法包括FIFO和FILO,在上一期发布的《OpenHarmony-内核对象队列之算法详解(上)》文章中,我分享了OpenHarmonyLiteOS-M内核对象队列的FIFO的算法,今天给大家介绍另外一种算法——FILO算法。

关键数据结构

首先关注队列的关键数据结构LosQueueCB,有了这个数据,才能理解队列是如何工作的:

typedef struct {
    UINT8 queue;      /< 消息队列内存区域的指针/
    UINT16 queueState; /*< 消息队列状态 /
    UINT16 queueLen;   /*< 消息队列状态个数 /
    UINT16 queueSize;  /*< 每个消息节点大小 /
    UINT16 queueID;    /*< 消息身份 /
    UINT16 queueHead;  /*< 消息队列的头部/
    UINT16 queueTail;  /*< 消息队列的尾部 /
    UINT16 readWriteableCnt[OS_READWRITE_LEN];  /*< 消息节点循环队列中读或写的消息个数/
    LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /*< 读或写消息阻塞链表/
    LOS_DL_LIST memList; /*< Pointer to the memory linked list /
  }LosQueueCB;

queue:指向消息节点内存区域,创建队列时按照消息节点个数乘每个节点大小从动态内存池中申请一片空间。  

queueState:队列状态,表明队列控制块是否被使用,有OS_QUEUE_INUSED和OS_QUEUE_UNUSED两种状态。  

queueLen:消息节点个数,表示该消息队列最大可存储多少个消息。  

queueSize:每个消息节点大小,表示队列每个消息可存储信息的大小。  

queueID:消息ID,通过它来操作队列。

消息节点按照循环队列的方式访问,队列中的每个节点以数组下标表示,下面的成员与消息节点循环队列有关: 

queueHead:循环队列的头部。 

queueTail:循环队列的尾部。 

readWriteableCnt[OS_QUEUE_WRITE]:消息节点循环队列中可写的消息个数,为0表示循环队列为满,等于queueLen表示循环队列为空。  

readWriteableCnt[OS_QUEUE_READ]:消息节点循环队列中可读的消息个数,为0表示循环队列为空,等于queueLen表示消息队列为满。  readWriteList[OS_QUEUE_WRITE]:写消息阻塞链表,链接因消息队列满而无法写入时需要挂起的TASK。  

readWriteList[OS_QUEUE_READ]:读消息阻塞链表,链接因消息队列空而无法读取时需要挂起的TASK。 

memList:申请内存块阻塞链表,链接因申请某一静态内存池中的内存块失败而需要挂起的TASK。  

关键算法

在计算机程序设计中,“先入先出”和“先入后出”都是处理输入数据的方法。上篇文章向大家介绍了FIFO(先入先出)算法,今天给大家讲解FILO(先入后出)算法。一个先入后出(FILO,First In Last Out)的队列,可以形象地理解为手枪的弹匣,装子弹是“入队列”,射击是“出队列”,最先压入弹匣的子弹是最后射出去的。同理,最先入队列的消息也是在最后处理,这就是FILO(先入后出)算法的本质。

1.1FIFO算法之入队列

第一步:队列初始化

下图呈现了一个初始化后的队列:   

截取关键函数LOS_QueueCreate,此函数来源于liteos_m内核代码。  

LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName,
                                         UINT16 len,
                                         UINT32 *queueID,
                                         UINT32 flags,
                                         UINT16 maxMsgSize)
{
    LosQueueCB *queueCB = NULL;
    UINT32 intSave;
    LOS_DL_LIST *unusedQueue = NULL;
    UINT8 *queue = NULL;
    UINT16 msgSize;
    ...
    queue = (UINT8 )LOS_MemAlloc(m_aucSysMem0, len  msgSize);
    ...
    queueCB->queueLen = len;
    queueCB->queueSize = msgSize;
    queueCB->queue = queue;
    queueCB->queueState = OS_QUEUE_INUSED;
    queueCB->readWriteableCnt[OS_QUEUE_READ] = 0;
    queueCB->readWriteableCnt[OS_QUEUE_WRITE] = len;
    queueCB->queueHead = 0;
    queueCB->queueTail = 0;
    LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_READ]);
    LOS_ListInit(&queueCB->readWriteList[OS_QUEUE_WRITE]);
    LOS_ListInit(&queueCB->memList);
    LOS_IntRestore(intSave);


    *queueID = queueCB->queueID;


    OsHookCall(LOS_HOOK_TYPE_QUEUE_CREATE, queueCB);


    return LOS_OK;
}

queue指针指向队列的内存,队列分配了len个消息,每个消息的大小为msgSize。与此同时头指针和尾指针的初始化为0,意味着队列为空,还没有消息入队列。

第二步:第一个消息入队列  

各类任务可以作为队列的生产者,队列初始化后,任务可以放置第一个消息,在此选择FILO的方式来放置消息。

下图是FIFO插入第一个数据后的内存形态:

FILO的操作包含在OsQueueBufferOperate函数中,这次是进入OS_QUEUE_WRITE_HEAD的分支处理:  

static INLINE VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType,
                                                            VOID bufferAddr, UINT32 bufferSize)
{
    UINT8 *queueNode = NULL;
    UINT32 msgDataSize;
    UINT16 queuePosition;
    errno_t rc;


    / get the queue position /
    switch (OS_QUEUE_OPERATE_GET(operateType)) {
        case OS_QUEUE_READ_HEAD:
            queuePosition = queueCB->queueHead;
            ((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
            break;


        case OS_QUEUE_WRITE_HEAD:
            (queueCB->queueHead == 0) ? (queueCB->queueHead = (queueCB->queueLen - 1)) : (--queueCB->queueHead);
            queuePosition = queueCB->queueHead;
            break;


        case OS_QUEUE_WRITE_TAIL:
            queuePosition = queueCB->queueTail;
            ((queueCB->queueTail + 1) == queueCB->queueLen) ? (queueCB->queueTail = 0) : (queueCB->queueTail++);
            break;
    ...
}

OsQueueBufferOperate是队列内存的核心操作函数,FILO算法的本质是往队列的头部添加数据,入队列的操作抽象为OS_QUEUE_WRITE_HEAD操作。而本次操作和FIFO不一样,插入数据不再移动tail这个“尾巴”指针,后续无论是入队列操作还是出队列操作,tail指针都不会被操作。

第三步:继续生产数据  

数据继续生产,第2个消息进入队列后继续移动head指针,如下图所示:

第三个消息也是重复的移动head指针,如下图所示:

第四步:生产数据结束  

本次实例以生产者生产四个消息为结束点,最后形态的队列下图所示: 

  

1.2 FIFO算法之出队列  

第一步:取出队列头消息。由于这是先入后出的算法,因此第一个出队列的消息是最后入队列的,也就是队列中标注为“第4个”的消息。  

消费后的消息空间也是unused空间,在此处用其它颜色标注消费后的消息,便于读者理解队列的变化情况。 

回顾一下OsQueueBufferOperate函数的关键代码,这一次是读的分支:  

/ get the queue position /
switch (OS_QUEUE_OPERATE_GET(operateType)) {
    case OS_QUEUE_READ_HEAD:
        queuePosition = queueCB->queueHead;
        ((queueCB->queueHead + 1) == queueCB->queueLen) ? (queueCB->queueHead = 0) : (queueCB->queueHead++);
        break;

queueHead是头指针,它的移动代表着出队列的行为,queueHead目前指向“第4个”消息,往后移动一个,应用得到“第4个”消息的返回值。此处可见,最后入队列的消息最先出。  

第二步:继续消费  

第三个消息被消费的图示:

第二个消息被消费的图示:

第三步:消费完毕  

最后一个消息也处理完成,于是head指针和tail指针均移动到下图的位置。队列为空,任务结束。  

这时如果把图重新换个方向来看,那么就很容易了解这个算法的本质。Tail指针全程没有用到,如果把它去掉,水平方向的队列改为垂直方向。如下图所示,可见该图片为典型的入栈操作。由此可知,OpenHarmony内核通过头指针的写操作和读操作,把栈的操作兼容到队列中。

总结

本文主要介绍了OpenHarmony内核对象队列的算法之FILO,至此,队列的2个算法都已介绍完毕。通过对FIFO和FILO这2个算法的详解,开发者能够更加全面了解OpenHarmony LiteOS-M 内核队列算法,以便将来在内核开发工作中遇到队列的其他算法,也能够举一反三,迅速掌握。

OpenHarmony内核编程实战 或者说内核在一个操作系统中起到一个什么样的作用?相信初次接触这个词的伙伴们也会有同样的疑问。不过不用担心,笔者会尽可能地通俗地介绍内核的相关知识,以便大家能够更好地去体会内核编程。我们先来看一张图,这是OpenHarmony官网发布的技术架构图我们可以看到最底层叫做内核层,有Linux,LiteOS等。内核在整个架构,或者操作系统中起到一个核心作用,他负责管理计算机系统内的资源和硬件设备,提供给顶层的应用层一个统一规范的接口,从而使得整个系统能够完成应用与硬件的交互。 阅读详情

相关推荐

OpenHarmony(鸿蒙南向开发)——子系统开发内核

OpenHarmony的Linux内核基于开源Linux内核LTS分支演进,在此基线基础上,回合CVE补丁及OpenHarmony特性,作为OpenHarmony Common Kernel基线。针对不同的芯片,各厂商合入对应的板级驱动补丁,完成对OpenHarmony的基线适配。Linux社区LTS 4.19.y分支信息请查看kernel官网。Linux社区LTS 5.10.y分支信息请查看kernel官网。

maniuT的博客 2010

OpenHarmony学习笔记(内核介绍)

本文内容为自己学习OpenHarmony中LiteOS的学习笔记及心得,因本人能力有限,内容或有错漏,请多包涵。本文会反复修正,持续更新。

weixin_49591408的博客 4506

【鸿蒙南向开发】OpenHarmony——内核对象队列之算法详解(上)

这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS_666的博客 552

OpenHarmony系统的微内核

但是5G时代,一个万物互联(Internet of Things, IoT)的时代,将有更多的小型智能设备接入互联网,低功耗、低内存、安全性成为了新的要求,在这些设备上跑宏内核的系统绝对不是好的选择,由此,微内核的热度又起来了。也就是说,宏内核提供了大量的冗余功能,兼容了太多的硬件,代码量自然就大。我们常说的Linux/UNIX就是基于宏内核的,内核提供了相当多的功能,包括驱动,调度器,地址空间管理,进程间通信,文件系统,虚拟文件系统,系统调用等,以Linux为例,其宏内核的代码量高达2700万行。

程序猿老樊的博客 1963

【鸿蒙实战开发】OpenHarmony——内核对象队列之算法详解(下)

这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS_666的博客 903

鸿蒙开发进阶(OpenHarmony)内核通信消息队列

消息队列又称队列,是一种任务间通信的机制。消息队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。

WEZC156465的博客 1074

OpenHarmony内核对象队列之算法详解

OpenAtom OpenHarmony(以下简称“OpenHarmony”) LiteOS-M 内核是面向 IoT 领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。在嵌入式领域的开发工作中,无论是自研还是移植系统,均绕不开内核,开发者只有掌握内核的相关知识,才能更好地深耕物联网产品领域。本文主要介绍了OpenHarmony内核对象队列的算法之FILO,至此,队列的2个算法都已介绍完毕。

xianglizaibie的博客 1074

OpenHarmony 实战开发——内核IPC机制数据结构解析

队列控制块:管理具体消息队列的数据块,内核初始化时调用OsQueueInit()创建,并依次挂载到双向环形链表g_freeQueueList中,此时控制块状态为OS_QUEUE_UNUSED,队列控制块用来保存队列的状态,队列长度、消息长度、队列ID、队列头尾位置和等待读写的任务列表,内核就是根据这些信息来管理消息队列和任务完成对消息读写等操作。任意时刻互斥锁的状态只有开锁或闭锁,当有任务持有时,互斥锁处于闭锁状态,任务获得该互斥锁的所有权;当该任务释放它时,互斥锁被开锁,任务失去该互斥锁的所有权;

maniuT的博客 1050

OpenHarmony——内核对象队列之算法详解

OpenAtom OpenHarmony(以下简称“OpenHarmony”) LiteOS-M 内核是面向 IoT 领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。在嵌入式领域的开发工作中,无论是自研还是移植系统,均绕不开内核,开发者只有掌握内核的相关知识,才能更好地深耕物联网产品领域。

鸿蒙开发知识记录 468

OpenHarmony——内核IPC机制数据结构解析

管理具体消息队列的数据块,内核初始化时调用OsQueueInit()创建,并依次挂载到双向环形链表g_freeQueueList中,此时控制块状态为OS\_QUEUE\_UNUSED,队列控制块用来保存队列的状态,队列长度、消息长度、队列ID、队列头尾位置和等待读写的任务列表,内核就是根据这些信息来管理消息队列和任务完成对消息读写等操作。当该任务释放它时,互斥锁被开锁,任务失去该互斥锁的所有权;事件用于实现任务间的同步,但事件通信只能是事件类型的通信,无数据传输,事件控制块由任务申请,内核负责维护。

2401_85015477的博客 1066

OpenHarmony轻量级内核-LiteOS-M

内核是一人操作系统的运算核心,决定着系统的性能和稳定性。它是基于硬件的第一层软件扩充,提供操作系统的基本功能,是操作系统工作的基础。它负责管理系统的进程、内存、外设驱动程序、支件和网络系统

lanlingxueyu的博客 3173

OpenHarmony实战开发——内核对象队列之算法详解

OpenAtom OpenHarmony(以下简称“OpenHarmony”) LiteOS-M 内核是面向 IoT 领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。在嵌入式领域的开发工作中,无论是自研还是移植系统,均绕不开内核,开发者只有掌握内核的相关知识,才能更好地深耕物联网产品领域。OpenHarmony LiteOS-M内核对象队列的算法包括FIFO和FILO,今天给大家介绍另外一种算法——FILO算法。

adaedwa187545的博客 771

【OpenHarmony内核】Harmony内核信号队列

在OpenHarmony内核中,信号队列是一项关键的功能,它为系统中不同组件之间的通信提供了一种有效而灵活的方式。信号队列的引入使得各个部分能够以协调的方式进行工作,从而增强了系统的响应性和可维护性。信号队列是一种数据结构,允许一个线程向另一个线程发送消息或信号。这些消息可以是简单的通知,也可以携带有关事件的信息。在OpenHarmony内核中,信号队列允许不同任务之间以异步的方式进行通信,而无需直接共享内存或直接调用对方的函数。信号队列的核心思想是发送者将消息放入队列,而接收者则从队列中获取消息。

m0_62599305的博客 711

OpenHarmony 实战开发——内核对象队列之算法详解

本文主要介绍了OpenHarmony内核对象队列的算法之FILO,至此,队列的2个算法都已介绍完毕。通过对FIFO和FILO这2个算法的详解,开发者能够更加全面了解OpenHarmony LiteOS-M 内核队列算法,以便将来在内核开发工作中遇到队列的其他算法,也能够举一反三,迅速掌握。

maniuT的博客 937

电力抄表协议DL/T645和698.45到底有啥区别?一张图帮你选对协议

本文深入对比了电力抄表协议DL/T645和DL/T698.45的技术差异,从协议架构、报文结构、功能覆盖到实施成本进行全面分析。通过实际案例和数据,揭示698.45协议在通信效率、业务扩展性和长期成本上的优势,并提供清晰的选型决策流程图,帮助工程师根据具体需求选择最适合的电力抄表协议。

weixin_38168696的博客 401

从零构建AI智能体:阿里云百炼平台实战指南(一)

本文是阿里云百炼平台构建AI智能体的实战指南。文章详细阐述了从聊天机器人到具备自主规划与执行能力的AI智能体的概念演进,并手把手指导读者在百炼平台上快速创建专属智能体、编排复杂工作流,以及实现多智能体协同,为开发者提供一站式、低门槛的大模型应用开发解决方案。

ol7890123的博客 295

【OpenHarmony 5.0】鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列

系列篇已有专门讲位图管理的文章,自行翻看.简单说就是一个变量的位来标记对应队列中是否有任务,在位图调度下,任务优先级的值越小则代表具有越高的优先级,每当需要进行调度时,从最低位向最高位查找出第一个置 1 的位的所在位置,即为当前最高优先级,然后从对应优先级就绪队列获得相应的任务控制块,整个调度器的实现复杂度是 O(1),即无论任务多少,其调度时间是固定的。鸿蒙系统的调度是抢占式的,task分成32个优先级,如何快速的知道哪个队列是空的,哪个队列里有任务需要一个标识,而且要极高效的实现?答案是:位图调度器。

adaedwa187545的博客 1102

思科—OSPF多区域配置实验

实验目的:配置OSPF多区域,使得不同网段的PC互相ping通。 网络拓扑如下: R0的配置 Router>en Router#conf t Router(config)#int g0/1 Router(config-if)#ip add 192.168.1.1 255.255.255.0 Router(config-if)#no shut Router(config-if)#exit Router(config)#int g0/0 Router(config-if)#ip add 192.168.

m0_46237205的博客 1万+
上一篇: 本周四晚19:00知识赋能第4期直播丨OpenHarmony智能家居项目之设备控制实现
下一篇: 本周四晚19:00知识赋能第六期第5课丨OpenHarmony WiFi子系统
OpenHarmony开发者
博客等级 码龄5年 626粉丝 221原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值