当前位置: 首页 > 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.jsqmd.com/news/944759/

相关文章:

  • 显微操作系统怎么选?液压、电动、手动三大方案全面对比! - 实了个验
  • 基于贝叶斯网络和多源信息构建可靠性分析模型方法解析【附数据】
  • 2026北京除天牛攻略|木质家具被天牛蛀损?高效处理方案 - 苏易修缮
  • imFile下载管理器:5个颠覆性功能与3大实战技巧
  • Windows系统优化终极指南:Chris Titus Tech WinUtil一键管理工具完全教程
  • 连续使用三个月向量 API 中转站,它真的适配向量落地场景吗?
  • NJU OS 进程的地址空间
  • Vicuna-13B-Delta-v0完全指南:从LLaMA到智能聊天助手的蜕变之路
  • 2026重庆旅游导游TOP榜单|纯玩无购物小团与真实游客反馈 - 随峰国旅
  • Arduino步进电机旋钮控制RGB灯光:从物理交互到嵌入式系统实践
  • 自主几何内核技术突破:stltostp实现STL到STEP精度达0.001mm的无损重构
  • 解密AliceSoft游戏文件:alice-tools让你轻松修改游戏资源
  • 画BPMN工具推荐:从“能画”到“能落地”的选择指南
  • 在线DO仪十大品牌排行榜:2026年国产溶解氧仪表技术突围与精准选型指南 - 水质仪表品牌排行榜
  • 如何用Fan Control彻底解决PC风扇噪音与散热难题:从零到精通完整指南
  • 电脑获取安卓手机中app的APK
  • 鸿蒙南向开发教程 Day 7:互斥锁(Mutex)
  • 2026避坑指南|北京家庭天牛为什么总复发?16区根治方案+靠谱公司排名 - 苏易修缮
  • Ultimate Vocal Remover:5分钟快速掌握AI音频分离的终极指南
  • 北京 10 家防水补漏商家深度测评|卫生间、外墙、屋顶漏水维修怎么选?鑫兴晟达综合实力稳居榜首 - 吉林同城获客
  • 告别磁盘混乱:Czkawka文件管理工具实战指南
  • 实测Yi-9B-200K:如何用消费级GPU玩转200K超长文本处理?
  • Meta-Llama-3-8B-Instruct全面解析:Meta革命性80亿参数对话模型深度评测
  • Win11Debloat终极指南:一键清理Windows 11,提升51%系统性能
  • 生命在于变化的庖丁解牛
  • 2026重庆本地持证导游官方备案查询指南|正规导游筛选与避坑说明 - 随峰国旅
  • 2026年智能温控系统厂家推荐排行榜:精准控温与节能芯片技术实力深度解析 - 品牌企业推荐师(官方)
  • AI依赖症康复计划(企业级落地版):已验证于华为/阿里/微软内部培训,仅开放前200份完整SOP
  • 基于TI C2000的电动赛车数据采集系统:从传感器到可视化全链路设计
  • 从零搭建自动化心电图系统:仪表放大器、双T陷波滤波与LabVIEW心率检测