RT-Thread 中 的 事 件 集 ,也 就 是 其 他 RTOS 中 的 事 件 标 志 组 。事
件 集 也 是 线 程 ( 任 务 ) 间 同 步 的 一 种 机 制 。
前 面 介 绍 的 两 种 线 程 间 同 步 的 方 式( 信 号 量 和 互 斥 量 )都 是 一 对 一 ;
而 事 件 集 可 以 实 现 一 对 多 、 多 对 多 的 线 程 同 步 。 事 件 集 的 工 作 机 制
1. 理 解 事 件 集
多 个 事 件 的 集 合 用 一 个 32 位 无 符 号 整 型 变 量 来 表 示 ,变 量 的 每 一
位 代 表 一 个 事 件 , 线 程 通 过 “逻 辑 与 ” 或 “逻 辑 或 ” 将 一 个 或 多 个
事 件 关 联 起 来 , 形 成 事 件 组 合 。
RT-Thread 中 的 事 件 集 有 以 下 特 点 :
事 件 只 与 线 程 相 关 , 事 件 间 相 互 独 立 。
事 件 仅 用 于 同 步 , 不 提 供 数 据 传 输 功 能
事 件 无 排 队 性 ,即 多 次 发 送 同 一 个 事 件( 且 线 程 还 未 读 走 ),其 效
果 等 同 于 发 送 了 一 次 。
当 线 程 等 待 事 件 同 步 时 ,可 以 通 过 32 个 事 件 标 志 和 这 个 事 件 信 息
标 记 来 判 断 当 前 接 收 的 事 件 是 否 满 足 同 步 条 件 。
举 例 理 解 事 件 集 ,如 下 图 所 示 ,线 程 #1 的 事 件 标 志 中 第 1 位 和
第 30 位 被 置 位 , 等 待 事 件 发 生 。
逻 辑 与 ,则 表 示 线 程 #1 只 有 在 事 件 1 和 事 件 30 都 发 生 以 后 才
会 被 触 发 唤 醒 。
逻 辑 或 , 则 事 件 1 或 事 件 30 中 的 任 意 一 个 发 生 都 会 触 发 唤 醒 线
程 #1。
同 时 设 置 了 清 除 标 记 位 ,则 当 线 程 #1 唤 醒 后 将 主 动 把 事 件 1 和
事 件 30 清 为 零 , 否 则 事 件 标 志 将 依 然 存 在 ( 即 置 1) 。
2. 事 件 集 控 制 块
在 RT-Thread 中 ,操 作 系 统 管 理 事 件 的 数 据 结 构 称 为 事 件 集 控 制
块 , 由 结 构 体 struc t rt_event 表 示 。 另 外 , rt_event_t 表 示 的 是 事 件
集 的 句 柄 , 即 指 向 事 件 集 控 制 块 的 指 针 。
事 件 集 控 制 块 结 构 体 定 义 如 下 :
struct rt_event
{
/* 继承自 ipc_object 类 */
struct rt_ipc_object parent;
/* 事件集合,每一 bit 表示 1 个事件,bit 位的值可以标记某事件是否发生 */
rt_uint32_t set;
};
/* rt_event_t 是指向事件结构体的指针类型 */
typedef struct rt_event* rt_event_t;
rt_event 对 象 从 rt_ipc_objec t 中 派 生 , 由 IPC 容 器 管 理 。 结 构
体 rt_ipc_objec t 定 义 如 下 :
struct rt_object
{
char name[RT_NAME_MAX]; /* 内核对象名称 */
rt_uint8_t type; /* 内核对象类型 */
rt_uint8_t flag; /* 内核对象的参数 */
#ifdef RT_USING_MODULE
void *module_id; /* 应用程序模块 ID */
#endif
rt_list_t list; /* 内核对象管理链表 */
};
struct rt_ipc_object
{
struct rt_object parent; /* 继承自 rt_object */
rt_list_t suspend_thread; /* 挂起的线程链表 */
};
结 构 体 定 义 中 ,继 承 关 系 一 目 了 然 ,不 再 赘 述 。下 边 看 看 如 何 对 一
个 事 件 集 进 行 操 作 。 管 理 事 件 集
事 件 集 相 关 的 操 作 函 数 如 下 图 所 示 ,主 要 包 含 :创 建 /初 始 化 事 件 集 、
发 送 事 件 、 接 收 事 件 、 删 除 /脱 离 事 件 集 。
本 文 只 介 绍 常 用 的 几 种 系 统 函 数 。
1. 创 建 事 件 集
同 信 号 量 类 似 。 RT-Thread 事 件 集 创 建 也 有 两 种 方 式 : 动 态 创 建 、
静 态 初 始 化 。
动 态 创 建 一 个 事 件 集 的 函 数 接 口 如 下 ,调 用 这 个 函 数 创 建 一 个 事 件
集 时 ,内 核 首 先 创 建 一 个 事 件 集 控 制 块 ,然 后 对 其 进 行 基 本 的 初 始
化 。
rt_event_t rt_event_create(const char* name, rt_uint8_t flag);
参 数 name 为 事 件 集 的 名 称 ; flag 为 事 件 集 的 标 志 , 取 值
为 RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO,这 两 个 标 志 值 之 前 介
绍 过 。
创 建 成 功 ,返 回 事 件 控 制 块 的 句 柄 。创 建 失 败 ,则 返 回 RT_NULL。
调 用 这 个 函 数 接 口 时 ,系 统 会 从 对 象 管 理 器 中 分 配 一 个 事 件 集 对 象 ,
并 对 其 初 始 化 ; 然 后 初 始 化 父 类 IPC 对 象 。
静 态 创 建 事 件 集 有 两 步 :( 1)定 义 一 个 事 件 控 制 块 结 构 体 变 量( 2)
调 用 函 数 对 结 构 体 变 量 初 始 化 。
对 事 件 集 控 制 块 变 量 初 始 化 的 函 数 为 :
rt_err_t rt_event_init(rt_event_t event, const char* name, rt_uint8_t f
lag)
该 函 数 对 event 指 向 的 事 件 集 控 制 块 初 始 化 , 然 后 将 其 加 入 到 系 统
对 象 容 器 中 进 行 管 理 。
创 建 事 件 集 的 标 志 变 量 取 值 有 两 种 :
RT_IPC_FLAG_FIFO,等 待 事 件 集 的 线 程 按 照 先 进 先 出 的 方 式 进 行 排
列 。
RT_IPC_FLAG_PRIO,等 待 事 件 集 的 线 程 按 照 优 先 级 的 方 式 进 行 排 列 。
2. 发 送 事 件
RT-Thread 提 供 的 发 送 事 件 函 数 , 可 以 一 次 性 发 送 事 件 集 中 的 一
个 或 多 个 事 件 , 函 数 原 型 如 下 :
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set);
使 用 该 函 数 接 口 时 , 通 过 参 数 set 指 定 的 事 件 标 志 来 设 定 event 事
件 集 对 象 的 事 件 标 志 值 。 然 后 遍 历 等 待 在 event 事 件 集 对 象 上 的 等
待 线 程 链 表 , 判 断 是 否 有 线 程 的 事 件 激 活 要 求 与 当 前 event 对 象 事
件 标 志 值 匹 配 , 如 果 有 , 则 唤 醒 该 线 程 。
3. 接 收 事 件
一 个 事 件 集 对 象 可 以 同 时 等 待 接 收 多 个 事 件 ,内 核 有 两 种 方 式 唤 醒
等 待 事 件 集 的 线 程 :
逻 辑 与 , 表 示 只 有 当 所 有 等 待 的 事 件 都 发 生 时 才 激 活 线 程
逻 辑 或 , 只 要 有 一 个 等 待 的 事 件 发 生 就 激 活 线 程 。
接 收 事 件 的 函 数 原 型 如 下 :
rt_err_t rt_event_recv(rt_event_t event,
rt_uint32_t set,
rt_uint8_t option,
rt_int32_t timeout,
rt_uint32_t *recved)
调 用 这 个 函 数 时 , 系 统 首 先 根 据 set 参 数 和 接 收 选 项 option 来 判 断
它 要 接 收 的 事 件 是 否 发 生 了 。
函 数 的 各 个 参 数 解 释 如 下 :
参 数 描 述
event 事 件 集 控 制 块 指 针
set 接 收 线 程 等 待 的 事 件
参 数 描 述
option 接 收 选 项
timeout 等 待 事 件 的 超 时 时 间 , 单 位 系 统 时 钟 节 拍
recved 指 向 收 到 的 事 件
接 收 成 功 , 函 数 返 回 RT_EOK; 超 时 , 返 回 -RT_ETIMEOUT; 出 错 ,
则 返 回 -RT_ERROR。
参 数 option 的 取 值 如 下 :
/* 选择逻辑与或逻辑或的方式接收事件 */
#define RT_EVENT_FLAG_AND 0x01 /* 逻辑与 */
#define RT_EVENT_FLAG_OR 0x02 /* 逻辑或 */
/* 选择清除重置事件标志位 */
#define RT_EVENT_FLAG_CLEAR 0x04 /* 清除事件标志位 */
当 调 用 rt_event_rec v() 函 数 时 , 系 统 首 先 根 据 set 参 数 和 接 收 选
项 option 来 判 断 它 要 接 收 的 事 件 是 否 发 生 :
事 件 已 经 发 生 , 则 根 据 参 数 option 上 是 否 设 置
有 RT_EVENT_FLAG_CLEAR 来 决 定 是 否 重 置 事 件 的 相 对 应 的 标 志 位 。
将 发 送 的 事 件 标 志 位 填 充 到 recved 指 向 的 标 志 变 量 中 。
事 件 没 有 发 生 ,把 等 待 的 set 和 option 参 数 填 入 线 程 控 制 块 结 构 中 ,
然 后 线 程 进 入 到 挂 起 状 态 。直 到 等 待 的 事 件 满 足 条 件 或 等 待 时 间 超
过 指 定 的 时 间 。
若 超 时 时 间 设 置 为 零 ,则 表 示 线 程 在 调 用 这 个 函 数 接 收 事 件 ,若 不
满 足 要 求 时 , 不 再 等 待 , 直 接 返 回 -RT_ETIMEOUT。 实 战 演 练
举 例 来 说 明 事 件 集 操 作 函 数 的 用 法 ,代 码 如 下 。创 建 两 个 线 程 ,一
个 线 程 等 待 事 件 , 一 个 线 程 发 送 事 件 。
部分文件列表
| 文件名 |
大小 |
| RT-Thread快速入门-事件集.pdf |
261K |
全部评论(0)