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

鸿蒙南向开发教程 Day 6:事件标志组(Event Flags)

目标:掌握 OpenHarmony 轻量系统的事件标志组 API,实现多线程间的事件通知与同步
前置条件:已完成 Day 5 的延时教程


一、工程结构

app/ ├── BUILD.gn └── 04_event/ # 模块目录 ├── BUILD.gn └── demo.c # 事件标志组测试代码

1.1app/BUILD.gn

import("//build/lite/config/component/lite_component.gni") lite_component("app") { features = [ "04_event:event_demo", # 引用 04_event 模块 ] }

1.204_event/BUILD.gn

static_library("event_demo") { sources = [ "demo.c" ] include_dirs = [ "//utils/native/lite/include", "//kernel/liteos_m/components/cmsis/2.0", ] }

二、完整代码详解

2.1 全局变量定义

#include<stdio.h>#include<unistd.h>#include"ohos_init.h"#include"cmsis_os2.h"osThreadId_tTask1_ID;// Task1 线程 IDosThreadId_tTask2_ID;// Task2 线程 IDosEventFlagsId_tevent_ID;// 事件标志组 ID// 定义三个事件标志位(按位独立)uint32_tevent1_Flags=0x00000001U;// bit 0uint32_tevent2_Flags=0x00000002U;// bit 1uint32_tevent3_Flags=0x00000004U;// bit 2#defineTASK_STACK_SIZE1024// 线程栈大小#defineTASK_DELAY_TIME1// 延时 1 秒

事件标志位设计

标志二进制含义
event1_Flags0x00000001U...0001事件 1
event2_Flags0x00000002U...0010事件 2
event3_Flags0x00000004U...0100事件 3

每个事件占用独立的 bit 位,可同时设置/等待多个事件。

2.2 发送事件线程(Task1)

voidTask1(void){while(1){printf("enter Task 1.......\n");// 设置事件标志 1osEventFlagsSet(event_ID,event1_Flags);printf("send eventFlag1.......\n");sleep(TASK_DELAY_TIME);// 延时 1 秒// 设置事件标志 2osEventFlagsSet(event_ID,event2_Flags);printf("send eventFlag2.......\n");sleep(TASK_DELAY_TIME);// 设置事件标志 3osEventFlagsSet(event_ID,event3_Flags);printf("send eventFlag3.......\n");sleep(TASK_DELAY_TIME);}}

执行时序

Task1: set bit0 ──sleep(1s)── set bit1 ──sleep(1s)── set bit2 ──sleep(1s)──→ "event1" "event2" "event3"

2.3 接收事件线程(Task2)

voidTask2(void){uint32_tflags=0;while(1){// 等待三个事件标志全部置位(AND 关系)flags=osEventFlagsWait(event_ID,// 事件标志组 IDevent1_Flags|event2_Flags|event3_Flags,// 等待的位掩码osFlagsWaitAll,// 等待模式:全部置位osWaitForever// 超时时间:永久等待);printf("receive event is OK\n");}}

等待模式详解

模式说明
osFlagsWaitAny0或等待:任一标志置位即唤醒
osFlagsWaitAll1与等待:所有标志都置位才唤醒

本例使用osFlagsWaitAll:必须 bit0、bit1、bit2 全部置 1,Task2 才会唤醒。

2.4 系统入口

staticvoidkernel_event_example(void){printf("Enter kernel_event_example()!\n");// 1. 创建事件标志组event_ID=osEventFlagsNew(NULL);// NULL = 默认属性if(event_ID!=NULL){printf("ID = %d, Create event_ID is OK!\n",event_ID);}// 2. 配置线程属性osThreadAttr_ttaskOptions;taskOptions.name="Task1";taskOptions.attr_bits=0;taskOptions.cb_mem=NULL;taskOptions.cb_size=0;taskOptions.stack_mem=NULL;taskOptions.stack_size=TASK_STACK_SIZE;taskOptions.priority=osPriorityNormal;// 3. 创建 Task1(发送事件)Task1_ID=osThreadNew((osThreadFunc_t)Task1,NULL,&taskOptions);if(Task1_ID!=NULL){printf("ID = %d, Create Task1_ID is OK!\n",Task1_ID);}// 4. 创建 Task2(接收事件),复用 taskOptions 结构体taskOptions.name="Task2";Task2_ID=osThreadNew((osThreadFunc_t)Task2,NULL,&taskOptions);if(Task2_ID!=NULL){printf("ID = %d, Create Task2_ID is OK!\n",Task2_ID);}}SYS_RUN(kernel_event_example);// 系统启动入口

三、CMSIS-RTOS2 事件标志组 API 详解

3.1osEventFlagsNew— 创建事件标志组

osEventFlagsId_tosEventFlagsNew(constosEventFlagsAttr_t*attr);
参数说明
attr属性,NULL 为默认

返回值:事件标志组 ID,NULL 表示创建失败。

3.2osEventFlagsSet— 设置事件标志

uint32_tosEventFlagsSet(osEventFlagsId_tef_id,uint32_tflags);
参数说明
ef_id事件标志组 ID
flags要设置的位掩码

特点

  • 设置后,等待该标志的线程会被唤醒(如果条件满足)
  • 可一次设置多个位:osEventFlagsSet(event_ID, flag1 | flag2)

3.3osEventFlagsWait— 等待事件标志

uint32_tosEventFlagsWait(osEventFlagsId_tef_id,// 事件标志组 IDuint32_tflags,// 等待的位掩码uint32_toptions,// 等待模式 + 清除选项uint32_ttimeout// 超时时间(tick),osWaitForever = 永久);

options 组合

选项说明
osFlagsWaitAny0x00000000任一标志置位即唤醒
osFlagsWaitAll0x00000001所有标志置位才唤醒
osFlagsNoClear0x00000002唤醒后不自动清除标志

常用组合

  • osFlagsWaitAny:或等待,自动清除
  • osFlagsWaitAll:与等待,自动清除(本例使用)
  • osFlagsWaitAll | osFlagsNoClear:与等待,不清除(需手动osEventFlagsClear

3.4osEventFlagsClear— 清除事件标志

uint32_tosEventFlagsClear(osEventFlagsId_tef_id,uint32_tflags);

3.5osEventFlagsGet— 获取当前标志值

uint32_tosEventFlagsGet(osEventFlagsId_tef_id);

3.6osEventFlagsDelete— 删除事件标志组

osStatus_tosEventFlagsDelete(osEventFlagsId_tef_id);

四、执行流程时序图

时间轴 → Task1: [set bit0]────[sleep 1s]────[set bit1]────[sleep 1s]────[set bit2]────[sleep 1s]────→ "event1" "event2" "event3" event_ID 标志位: bit0=1 bit1=1 bit2=1 ───────────────────────────────────────────────────────────────────────────────→ Task2: [wait all bits]←──────────────────────────────────────────→[wakeup!]────────────→ Blocked状态 等待bit0&bit1&bit2全部置位 "receive event is OK"

关键:Task2 在第三次osEventFlagsSet后才唤醒,因为前两次 bit0 和 bit1 置位时,bit2 还未置位,不满足osFlagsWaitAll条件。


五、底层实现:LiteOS 原生事件

CMSIS-RTOS2 的osEventFlagsXxx在 LiteOS-M 中的映射:

CMSIS-RTOS2LiteOS-M 原生说明
osEventFlagsNewLOS_EventCreate创建事件控制块
osEventFlagsSetLOS_EventWrite写事件标志
osEventFlagsWaitLOS_EventRead读事件标志
osEventFlagsClearLOS_EventClear清除事件标志
osEventFlagsDeleteLOS_EventDelete删除事件控制块

LiteOS-M 使用事件控制块(Event Control Block)实现,内部维护一个 32 位事件标志字。


六、编译与验证

6.1 编译烧录

VSCode 点击BuildUpload,串口波特率115200

6.2 预期输出

Enter kernel_event_example()! ID = 20001xxx, Create event_ID is OK! ID = 20001yyy, Create Task1_ID is OK! ID = 20001zzz, Create Task2_ID is OK! enter Task 1....... send eventFlag1....... enter Task 1....... send eventFlag2....... enter Task 1....... send eventFlag3....... receive event is OK enter Task 1....... send eventFlag1....... ...

Task2 在 Task1 发送完三个事件后才打印 “receive event is OK”,验证了osFlagsWaitAll的与等待逻辑。


七、总结

要点内容
事件标志32 位独立位,可同时管理多个事件
设置事件osEventFlagsSet(id, flags)
等待事件osEventFlagsWait(id, flags, mode, timeout)
等待模式osFlagsWaitAny(或)/osFlagsWaitAll(与)
自动清除默认唤醒后自动清除,可加osFlagsNoClear保留
底层映射LiteOS-MLOS_EventXxx事件控制块

八、下一步

Day 7 预告:信号量(Semaphore)—— 资源计数与任务同步。

http://www.gsyq.cn/news/1456236.html

相关文章:

  • 基于贝叶斯网络和多源信息构建可靠性分析模型方法解析【附数据】
  • 连续使用三个月向量 API 中转站,它真的适配向量落地场景吗?
  • 自主几何内核技术突破:stltostp实现STL到STEP精度达0.001mm的无损重构
  • 鸿蒙南向开发教程 Day 7:互斥锁(Mutex)
  • 北京 10 家防水补漏商家深度测评|卫生间、外墙、屋顶漏水维修怎么选?鑫兴晟达综合实力稳居榜首 - 吉林同城获客
  • Ultimate Vocal Remover:5分钟快速掌握AI音频分离的终极指南
  • Meta-Llama-3-8B-Instruct全面解析:Meta革命性80亿参数对话模型深度评测
  • 生命在于变化的庖丁解牛
  • 2026年智能温控系统厂家推荐排行榜:精准控温与节能芯片技术实力深度解析 - 品牌企业推荐师(官方)
  • 基于TI C2000的电动赛车数据采集系统:从传感器到可视化全链路设计
  • 2026专业测评!北京木质家具遭天牛蛀蚀?16区正规消杀公司深度对比 - 苏易修缮
  • 2026年6月热门的短视频运营推荐,工厂短视频陪跑/短视频陪跑/制造业宣传片制作/工厂短视频制作,短视频运营多少钱一个月 - 品牌推荐师
  • 零基础玩转RVC语音克隆:5分钟打造专属AI声线
  • 2026 北京防水补漏 10 家商家实测测评|卫生间 / 外墙 / 屋顶 / 地下室渗漏维修优选指南 - 吉林同城获客
  • 【Excel数据工程实战】从 #N/A 到透视表漂移:一套可复用的排错与重构流程(附 Power Query 方案)
  • KMS智能激活解决方案:Windows与Office的终极免费激活指南
  • 2026北京防虫排名!家里有天牛怎么彻底根除?16区3家专业团队对比 - 苏易修缮
  • 主题模型在量化交易中的应用:GitHub_Trending/ma/machine-learning-for-trading LDA实战
  • DAIHEN AGA-27B 60MHz High Power Source 电源日本
  • 2026年在线悬浮物浓度计十大品牌权威排行榜:专业选型指南与深度技术解析 - 水质仪表品牌排行榜
  • 自然语言查询系统实战:从架构设计到工程落地的完整指南
  • 从手动到自动:WinUtil如何将Windows系统管理效率提升500%
  • Mobile-Agent架构深度解析:跨平台智能调度引擎的技术突破与实践指南
  • 基于GreenPAK的温度-频率转换器设计:用数字逻辑实现低成本温度监测
  • 从零开始:用Vin象棋AI助手3分钟打造你的私人象棋教练
  • PDF补丁丁终极指南:10个免费PDF处理技巧让你工作效率翻倍
  • 私藏找靠谱美发店必看!2026全年度高口碑深圳发型师推荐:6月烫头发/漂染头发/接发理发店哪家好揭秘!附发型师怎么选FAQ避坑要点! - 奋斗者888
  • 2026年除湿系统厂家推荐榜单:工业/商用/家用除湿机源头工厂,精准控湿与节能实力品牌深度解析! - 品牌企业推荐师(官方)
  • Windows系统优化工具箱:从手动配置到一键自动化
  • PyTorch自定义损失报错怎么办?教你一招避坑