当前位置:文档之家› 嵌入式操作系统教程-第九章

嵌入式操作系统教程-第九章

6
嵌 入 式 操 作 系 统 基 础
三、事件控制块
事件控制块的结构
typedef struct { void */ INT8U INT16U INT8U INT8U } OS_EVENT; *OSEventPtr; /* 指向消息或者消息队列的指针 */
OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待任务列表 OSEventCnt; OSEventType; OSEventGrp; /* 事件类型 */ */
22
嵌 入 式 操 作 系 统 基 础
第 九 章 任 务 的 同 步 与 d) { …… SetTaskPriority(RES_X_PRIO); //访问共享资源X SetTaskPriority(TASK_A_PRIO); ……
嵌 入 式 操 作 系 统 基 础
二、互斥型信号量
实现对共享资源的独占式处理。 解决任务的优先级反转:变量OSEventPtr占 16位,低8位作为信号量有效性的判断位; 高8位则存放任务运行后临时暂用的优先级 别。
3.发送一个信号量, OSSemPost() 发送一个信号量, 发送一个信号量 ()
任务获得信号量,并在访问共享资源结束以后,必须释 放信号量,此过程需调用函数OSSemPost()完成。
16
嵌 入 式 操 作 系 统 基 础
第 九 章 任 务 的 同 步 与 通 信
INT8U OSSemPost (OS_EVENT *pevent) { OS_ENTER_CRITICAL(); if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); } if (pevent->OSEventGrp) { OSEventTaskRdy(pevent, (void *)0, OS_STAT_SEM); OS_EXIT_CRITICAL(); OSSched(); return (OS_NO_ERR); } else { if (pevent->OSEventCnt < 65535) { pevent->OSEventCnt++; OS_EXIT_CRITICAL(); return (OS_NO_ERR); } else { OS_EXIT_CRITICAL(); return (OS_SEM_OVF); } } }
/* 计数器(当事件是信号量时) */ /* 等待任务所在的组
OSEventPtr指针,只有在所定义的事件是邮箱或者消息队 列时才使用。当所定义的事件是邮箱时,它指向一个消 息,而当所定义的事件是消息队列时,它指向一个数据 结构。
7
嵌 入 式 操 作 系 统 基 础
.OSEventTbl[] /.OSEventGrp 与前面提过的OSRdyTbl[]和
4
嵌 入 式 操 作 系 统 基 础
3.消息队列
若消息邮箱被定义成拥有若干个元素的数 组,用来传递多个消息的地址指针,这样消 息的数据结构称为消息队列。
4.事件的等待任务队列
两个功能: 对等待事件的所有记录进行登记并排序 允许任务有一定的等待时间
5
嵌 入 式 操 作 系 统 基 础
第 九 章 任 务 的 同 步 与 通 信
在可剥夺型内核中,当任务以独占方式使用共享资源时, 会出现低优先级任务先于高优先级任务而被运行的现象,这 种现象就成为任务优先级反转。
19
嵌 入 式 操 作 系 统 基 础
形成原因:使用信号量的任务是否能够运行时受任务的优先 级别以及是否占用信号量两个条件约束的,而信号量的约束 高于优先级别的约束。 解决方案:一旦获取信号量的任务投入运行,其将暂用最高 优先级别,直至任务执行完成。
2
嵌 入 式 操 作 系 统 基 础
1.信号量
互斥型信号量:通常表现为一个二值型信号,用一 位二进制位来表示(1/0),可以实现共享资源的独 占式占用。
信号量:通常表现为一个递减的计数器信号,可以 实现若干个同类资源的共享,提高资源使用效率。
3
嵌 入 式 操 作 系 统 基 础
2.消息邮箱
指向保存任务间传递信息的存储空间(缓存 区)的指针结构称为消息邮箱。
(1)
(2) (3) (4)
(5)
17
嵌 入 式 操 作 系 统 基 础
3.发送一个信号量, OSSemPost() 发送一个信号量, 发送一个信号量 ()
OS_EVENT *OSSemDel( OS_EVENT *pevent, Typedef struct{ INT16U OSCnt; INT8U opt, INTU8U OSEventb1[OS_EVENT_SIZE]; INT8U *err INT8U OSEventGrp; ); }OS_SEM_DATA;
函数作用:把变量OSEventGrp及任务等待表中的每一 位都清0,即令事件的任务等代表中不含有任何等待任 务。
9
嵌 入 式 操 作 系 统 基 础
void OSEventTaskWait (OS_EVENT *pevent) { OSTCBCur->OSTCBEventPtr = pevent; if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; pevent->OSEventGrp } |= OSTCBCur->OSTCBBitY; (3) (1) (2)
{
信号量 OS_EVENT *pevent; 创建 OS_ENTER_CRITICAL(); pevent = OSEventFreeList; (1) if (OSEventFreeList != (OS_EVENT *)0) { (2) OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } OS_EXIT_CRITICAL(); if (pevent != (OS_EVENT *)0) { (3) pevent->OSEventType = OS_EVENT_TYPE_SEM;(4) pevent->OSEventCnt = cnt; (5) OSEventWaitListInit(pevent); (6) } return (pevent); (7)
OSRdyGrp非常相像,只不过前两者包含的是等待某事件 的任务,而后两者包含的是系统中处于就绪状态的任务。 .OSEventCnt :当事件是一个信号量时,.OSEventCnt是用 于信号量的计数器。 .OSEventType: .OSEventType:定义了事件的具体类型。它可以是信号量 (OS_EVENT_SEM)、邮箱(OS_EVENT_TYPE_MBOX) 或消息队列(OS_EVENT_TYPE_Q)中的一种。用户要根 据该域的具体值来调用相应的系统函数,以保证对其进行 的操作的正确性。
3.信号量状态查询, OSSemQuery() 信号量状态查询, 信号量状态查询 ()
INT8U OSSemQuery( OS_EVENT *pevent, OS_SEM_DATA *pdata );
18
嵌 入 式 操 作 系 统 基 础
§9.3 任务优先级反转和互斥型信号量
一、任务优先级的反转现象
15
}
嵌 入 式 操 作 系 统 基 础
2.等待一个信号量,
OSSemPend()/OSSemAccept()
void OSSemPend(OS_EVENT *pevent, //信号量指针 INT16U timeout, INT8U *err); INT16U OSSEMAccept( OS_EVENT *PEVENT //信号量指针 ) //等待时限 //错误信息
第 九 章 任 务 的 同 步 与 通 信
8
嵌 入 式 操 作 系 统 基 础
四、事件控制块的基本操作函数
1.事件控制块的初始话函数
void OSEventWaitListInit (OS_EVENT *pevent) { INT8U i; pevent->OSEventGrp = 0x00; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { pevent->OSEventTbl[i] = 0x00; } }
4.等待超时的任务转为就绪态
void OSEventTO (OS_EVENT *pevent) { if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (1) pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
正在等待事件的任务在预先指定的时间内仍然没有 获取事件,这时需调用此函数来转换的它的状态。
12
嵌 入 式 操 作 系 统 基 础
五、空事件控制块的的组织
和任务控制块的组织结构类似:所有的事件控制 块也被组织成两个链表,当系统初始化时,通过控 制块指针OSEventPtr把所有的空时间控制块链接成 一个空事件控制块链表。
2.使一个任务进入等待状态的函数
当一个任务在请求一个事件而不能获得时,应把次任 务登记在时间的等待任务列表中,并把任务控制块中的任 务状态置为等待状态和吧任务置为非就绪任务
相关主题