0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenHarmony内核任务间IPC原理

2KHh_gh_15d2f06 来源:深开鸿 作者:深开鸿 2022-07-12 16:45 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

近年来,国内开源实现跨越式发展,并成为企业提升创新能力、生产力、协作和透明度的关键。作为 OpenAtom OpenHarmony(以下简称“OpenHarmony”)开源项目共建单位之一,深开鸿以成为智能物联网操作系统领军者为战略目标,基于 OpenHarmony 聚焦智能物联网操作系统(KaihongOS)的技术研发与持续创新。

身为深开鸿 OS 内核开发师,我们常年深耕于 OpenHarmony 的内核开发,希望通过分享一些工作上的经验,帮助大家掌握开源知识。

OpenHarmony LiteOS-M 内核是面向 IoT 领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点,其代码结构简单,实现了进程、线程、内存等管理机制,提供了常见任务间 IPC、软定时器等公共模块,大幅度降低了嵌入式设备开发的难度。目前 OpenHarmony 的事件提供一种任务间的 IPC,即一个或多个任务可以通过写一个或多个不同的事件来触发内核调度,让另一个等待读取事件的任务进入运行状态,从而实现任务间的同步。

对于嵌入式开发工作人员和技术爱好者来说,深入了解常见任务间 IPC,有助于学习和研发内核。本文将从数据结构和算法解析 OpenHarmony 的事件机制,带大家深入了解内核任务间 IPC 原理。

关键数据结构

在解读事件的源码之前,首先了解下事件的关键的数据结构 PEVENT_CB_S:

typedefstructtagEvent{    UINT32 uwEventID;           LOS_DL_LIST stEventList; /**< Event control block linked list */  } EVENT_CB_S, *PEVENT_CB_S;

uwEventID:即标记任务的事件类型,每个bit可以标识一个事件,最多支持 31 个事件(第 25bit 保留)。

stEventList:即事件控制块的双向循环链表,理解这个字段是理解事件的关键。在双向循环链表中唯一不变的节点就是头节点,而这里的 stEventList 就是头节点。当有任务等待事件但事件还没发生时,任务会被挂载到等待链表中;当事件发生时,系统唤醒等待事件的任务,此时任务就会被剔出链表。

事件初始化

下面是事件初始化源码:

LITE_OS_SEC_TEXT_INITUINT32LOS_EventInit(PEVENT_CB_SeventCB){    if (eventCB == NULL) {        return LOS_ERRNO_EVENT_PTR_NULL;    }    eventCB->uwEventID = 0;    LOS_ListInit(&eventCB->stEventList);    OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB);    return LOS_OK;}

PEVENT_CB_S 相当于 EVENT_CB_S *, 因此 eventCB 是指针。

说明事件控制块由任务自己创建,内核事件模块只负责维护。任务定义自己的事件控制块变量,通过 LOS_EventInit 初始化,此时没有事件发生,事件链表为空。

用图来表达就是:

fde8ee4c-ed2a-11ec-ba43-dac502259ad0.png

事件写操作

任务可以通过 LOS_EventWrite 来写触发一个或多个事件:

LITE_OS_SEC_TEXTUINT32LOS_EventWrite(PEVENT_CB_SeventCB,UINT32events){    ...    eventCB->uwEventID |= events;                    ---1    if (!LOS_ListEmpty(&eventCB->stEventList)) {     ---2        for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);             &resumedTask->pendList != (&eventCB->stEventList);) { -------3            nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);
            if (((resumedTask->eventMode & LOS_WAITMODE_OR) && (resumedTask->eventMask & events) != 0) ||                ((resumedTask->eventMode & LOS_WAITMODE_AND) &&                 ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {                exitFlag = 1;
                OsSchedTaskWake(resumedTask);       ---4            }            resumedTask = nextTask;        }
        if (exitFlag == 1) {            LOS_IntRestore(intSave);            LOS_Schedule();                        ---5            return LOS_OK;        }    }    ...}

1处,保存事件使用的或运算操作,因此一个或多个任务可以写一个或多个事件,写一次或多次,而且每次为不同的事件,多次写同一个事件相当于只写了一次;

2处,有事件发生了就该检查是否有任务在等待事件,事件链表不为空说明有任务在等待事件;

3处,遍历事件链表,唤醒符合条件的任务。LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext,LosTaskCB,pendList) 前面提到,头节点是空节点,第一次遍历从头节点的下一个节点开始,后续再依次找出 nextTask,直到回到头节点;

4处,针对事件读取模式,找到满足条件的任务并唤醒该任务;

5处,一旦匹配到等待事件的任务,则执行任务调度,被唤醒的任务得到执行。

写事件实际操作如下图:

fe029ed2-ed2a-11ec-ba43-dac502259ad0.png

事件读操作

LiteOS 为用户提供了两个事件的函数:

● LOS_EventPoll():根据任务传入的事件值、掩码及校验模式,返回满足条件的事件,任务可以主动检查事件是否发生而不必被挂起;

● LOS_EventRead():读取事件,可以理解为阻塞式读,如果事件没有发生,可以指定等待时间,挂起当前任务。

下面是 LOS_EventPoll() 的实现:

LITE_OS_SEC_TEXTUINT32LOS_EventPoll(UINT32*eventID,UINT32eventMask,UINT32mode){    UINT32 ret = 0;    UINT32 intSave;
    if (eventID == NULL) {        return LOS_ERRNO_EVENT_PTR_NULL;    }    intSave = LOS_IntLock();    if (mode & LOS_WAITMODE_OR) {        if ((*eventID & eventMask) != 0) {      ---1            ret = *eventID & eventMask;        }    } else {        if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {   ---2            ret = *eventID & eventMask;        }    }    if (ret && (mode & LOS_WAITMODE_CLR)) {   ---3        *eventID = *eventID & ~(ret);    }    LOS_IntRestore(intSave);    return ret;}

1处,如果读取模式是LOS_WAITMODE_OR,只要有一个事件发生则读取成功,返回发生的那个事件;

2处,如果读取模式LOS_WAITMODE_AND,全部检查事件发生才算读取成功,并返回全部发生事件;

3处,事件读取成功后事件控制块中的事件标记怎么处理?这里通过LOS_WAITMODE_CLR来决定是否清除事件标记。

可以看出以上实现了两种事件的读取方式:一种是多个事件只要一个发生就算发生,另一种是全部事件发生才算发生。

下面是 LOS_EventRead():

LITE_OS_SEC_TEXTUINT32LOS_EventRead(PEVENT_CB_SeventCB,UINT32eventMask,UINT32mode,UINT32timeOut){    ...    ret = LOS_EventPoll(&(eventCB->uwEventID), eventMask, mode);           ---1    OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeOut);    if (ret == 0) {        if (timeOut == 0) {            LOS_IntRestore(intSave);            return ret;        }
        if (g_losTaskLock) {            LOS_IntRestore(intSave);            return LOS_ERRNO_EVENT_READ_IN_LOCK;        }        runTsk = g_losTask.runTask;        runTsk->eventMask = eventMask;        runTsk->eventMode = mode;        OsSchedTaskWait(&eventCB->stEventList, timeOut);                  ---2        LOS_IntRestore(intSave);        LOS_Schedule();                                                   ---3
        intSave = LOS_IntLock();        if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) {            runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT;            LOS_IntRestore(intSave);            return LOS_ERRNO_EVENT_READ_TIMEOUT;        }
        ret = LOS_EventPoll(&eventCB->uwEventID, eventMask, mode);       ---4    }     ...}

1处,主动查询想要的事件是否已经发生;

2处,如果事件没有发生,就把当前任务挂起到等待事件链表中;

3处,如果事件没有发生,当前读事件的任务被挂起,让出 CPU

4处,事件发生时等待事件的任务被调度再次获得 CPU 恢复执行,读取事件。

事件读写整个过程串起来如下图所示:

fe0b2066-ed2a-11ec-ba43-dac502259ad0.png

事件销毁操作

做事有始有终,事件消费完成剩下的事情是清除事件和等待事件的任务链表。

LITE_OS_SEC_TEXT_MINORUINT32LOS_EventClear(PEVENT_CB_SeventCB,UINT32eventMask){    ...    eventCB->uwEventID &= eventMask;    ...}

LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB){    ...    eventCB->stEventList.pstNext = (LOS_DL_LIST *)NULL;    eventCB->stEventList.pstPrev = (LOS_DL_LIST *)NULL;    ...}

在LOS_EventClear 中通过使 eventMask=0 来清空事件,在 LOS_EventDestroy 中清空事件链表指针。

小结


看了上面的描述,相信大家对 OpenHarmony LiteOS-M 内核事件的运作机制有了更加深刻的理解,开发者可以更好地使用事件的 API 来进行任务间的同步操作,也可以进一步尝试修改内核事件通知机制,做出一个更适合自己任务的IPC机制。

OpenHarmony 生态建设离不开每位开发者的参与,希望有更多的开发者分享自己开源项目的经验和成果,共同为 OpenHarmony 生态建设贡献一份力量。

原文标题:OpenHarmony——内核对象事件之源码详解

文章出处:【微信公众号:深开鸿】欢迎添加关注!文章转载请注明出处。

审核编辑:彭静

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11217

    浏览量

    222952
  • 操作系统
    +关注

    关注

    37

    文章

    7328

    浏览量

    128634
  • IPC
    IPC
    +关注

    关注

    3

    文章

    375

    浏览量

    54553
  • 数据结构
    +关注

    关注

    3

    文章

    573

    浏览量

    41374
  • OpenHarmony
    +关注

    关注

    31

    文章

    3926

    浏览量

    20721

原文标题:OpenHarmony——内核对象事件之源码详解

文章出处:【微信号:gh_15d2f062a168,微信公众号:深开鸿】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux进程通信(IPC)全解析:从管道到 Socket,一篇讲透

    在 Linux 世界里,进程并非孤立存在。无论是后台服务协作(如 Web 服务器与数据库)、命令行工具联动(如ps | grep),还是复杂应用的模块通信,都离不开 进程通信(IPC
    的头像 发表于 11-14 21:38 1.2w次阅读
    Linux进程<b class='flag-5'>间</b>通信(<b class='flag-5'>IPC</b>)全解析:从管道到 Socket,一篇讲透

    两款搭载KaihongOS的开鸿开发板被评为“OpenHarmony 明星开发板”

    OpenHarmony
    深开鸿
    发布于 :2025年09月11日 10:10:02

    活动预告 | OpenHarmony论文解读系列直播第三期

      直播 OpenHarmony-TSC 扫码观看直播 审核编辑 黄宇  
    的头像 发表于 08-23 16:48 609次阅读
    活动预告 | <b class='flag-5'>OpenHarmony</b>论文解读系列直播第三期

    IPC监控摄像头与边缘计算盒子:选购安装全攻略

    在智能AI安防场景,IPC监控摄像头、智能安防监控摄像头或AI视觉IPC智能摄像头的应用往往都需要联动使用边缘计算盒子或边缘计算服务器。在选择IPC监控摄像头和边缘计算服务器厂商以及进行安装时,客户
    的头像 发表于 07-31 09:45 632次阅读
    <b class='flag-5'>IPC</b>监控摄像头与边缘计算盒子:选购安装全攻略

    迅为RK3568开发板OpeHarmony学习开发手册1.1-内核移植优化

    。如果把这份源码复制到 Openharmony 根目录下,修改编译脚本,使得每次编译的时候不用打原始内核 补 丁 了 , 这 样 编 译 的 时 候 , 每 次 将 Openharmony 根 目 录
    发表于 07-26 10:37

    第三届大会回顾第5期 | OpenHarmony内核实时性探索

    实时性是操作系统内核在特定应用场景中不可或缺的特性,它通过多种技术手段确保系统在规定时间内完成任务,从而满足高可靠性、高响应速度的需求。
    的头像 发表于 06-25 18:02 805次阅读
    第三届大会回顾第5期 | <b class='flag-5'>OpenHarmony</b><b class='flag-5'>内核</b>实时性探索

    请问下,openharmony支持哪一款龙芯的开发板?有没有开源的龙芯的openharmony源码?

    想买个2k0300的开发板学习龙芯和openharmony,愣是没有看到提供openharmony源码的,也没与看到开源的代码。gitee上,openharmony的龙芯sig仓库也是关闭的,有没有人知道现在是什么情况?
    发表于 04-26 13:06

    2024年OpenHarmony社区年度激励公示

    交通大学 古金宇 OpenHarmony TEE操作系统内核 叁万元 领航课题 北京航空航天大学 黎立 针对Open
    的头像 发表于 04-21 18:17 935次阅读

    极致制造,严苛标准——捷多邦如何做到IPC Class 3级别PCB质量?

    服务商,捷多邦凭借精密工艺、严格质检、先进设备,确保每一块PCB都符合甚至超越IPC Class 3标准,为客户提供更稳定、更耐用的电路板。 IPC Class 3的核心要求 IPC Class 3对PCB的导通孔可靠性、层
    的头像 发表于 03-21 17:24 1761次阅读

    IPC2221简略学习笔记

    关于IPC2221的学习笔记。
    发表于 03-14 18:07 7次下载

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构
    的头像 发表于 03-11 14:13 1559次阅读
    北京迅为RK3568开发板<b class='flag-5'>OpenHarmony</b>系统南向驱动开发<b class='flag-5'>内核</b>HDF驱动框架架构

    迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-添加内核编译

    编译内核时将该 HDF 驱动编译到镜像中,接下来编写驱动编译脚本 Makefile,代码如下所示: 加入编译体系,填加模块目录到 drivers/hdf_core/adapter/khdf/linux/Makefile 文件 更多内容可以关注:迅为RK3568开发板篇OpenHa
    发表于 01-22 10:35

    迅为RK3568开发板篇OpenHarmony配置HDF驱动控制LED-新增 topeet子系统

    目录 ├── led_driver.c:内核 LED HDF 驱动程序 └── Makefile:内核 LED HDF 驱动编译脚本 更多内容可以关注:迅为RK3568开发板篇OpenHarmony
    发表于 01-13 15:59

    博泰车联网厦门制造基地顺利通过IPC QML审核

    近日,博泰车联网厦门制造基地经过IPC严格的审核,生产工艺与产品质量符合电子行业国际标准IPC-A-610《电子组件的可接受性》三级产品要求与IPC J-STD-001《焊接的电气与电子组件要求》,顺利通过
    的头像 发表于 01-02 14:20 978次阅读

    OpenHarmony程序分析框架论文入选ICSE 2025

      近日,ICSE 2025软件工程实践Track放榜,面向OpenAtom OpenHarmony(以下简称“OpenHarmony”)的ArkTS程序分析基础框架--方舟程序分析器(论文题目为
    的头像 发表于 01-02 13:41 1839次阅读
    <b class='flag-5'>OpenHarmony</b>程序分析框架论文入选ICSE 2025