chap08-互斥型信号量管理_第1页
chap08-互斥型信号量管理_第2页
chap08-互斥型信号量管理_第3页
chap08-互斥型信号量管理_第4页
chap08-互斥型信号量管理_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1,2020/8/12,嵌入式实时操作系统 C/OS-II,2020/8/12,2,第8章 互斥型信号量管理,所谓的互斥型信号量(mutual exclusion semaphores,也称作mutex)是一个二值信号量,简称为 “信号” ,它是一种特殊的信号量,主要用于处理任务对共享资源独占问题。 使用互斥型信号量时要注意任务优先级反转的问题。,3,举例: 有3个任务使用某共享资源。为得到该资源,每个任务都有可能因得不到互斥型信号量而被挂起(pend)。任务1的优先级最高(10),任务2中等(15),任务3最低(20)。没有被占用的、略高于最高优先级任务的优先级(9),保留给“优先级继承优先

2、级”PIP(Priority Inheritance Priority)。,4,OS_EVENT *ResourceMutex; OS_STK TaskPrio10Stk1000; OS_STK TaskPrio15Stk1000; OS_STK TaskPrio20Stk1000; void main(void) INT8U err; OSInit(); -应用程序初始化- ResourceMutex = OSMutexCreate(9, ,5,void TaskPrio10(void *pdata) INT8U err; pdata = pdata; while(1) -应用程序代码- O

3、SMutexPend(ResourceMutex, 0, -应用程序代码- ,6,void TaskPrio15(void *pdata) INT8U err; pdata = pdata; while(1) -应用程序代码- OSMutexPend(ResourceMutex, 0, -应用程序代码- ,7,void TaskPrio20(void *pdata) INT8U err; pdata = pdata; while(1) -应用程序代码- OSMutexPend(ResourceMutex, 0, -应用程序代码- ,8,任务优先级的反转现象,是指在剥夺式OS中,当任务以独占方式

4、使用共享资源时,低优先级的任务可能先于高优先级任务得到系统调度而运行的现象。,9,任务优先级的反转现象分析,造成的结果:Task_B 优先于 Task_A 得到运行。 问题的严重性:如果Task_B之类的任务较多时,甚至会影响系统的设计目标。 原因:低优先级的任务独占共享资源,迫使高优先级任务因等待资源而让出CPU。 解决办法:暂时提升获得共享资源任务的优先级别,尽快释放共享资源,之后再恢复其原有的优先级别。,备注:决定任务得到运行的条件不仅仅是优先级,还有任务所需的资源。,10,解决方法: 将任务3的优先级提升至9,并强制任务调度回到任务3。,11,用户要在OS_CFG.H中将OS_MUTE

5、X_EN 开关量常数置成1,这样C/OS-II 才能支持信号量。,表 OS_CFG.H中的信号量配置常数,12,互斥型信号量(Mutex),互斥型信号量是一个二值信号量,是一种处理“任务优先级反转”现象的特殊信号量,主要用于处理任务对共享资源独占问题。为此,“事件” 数据结构上有一些特约: 将OSEventCnt拆为了高8位(prio事件优先级)和低8位(资源标志)两个成员。,13,事件控制块-(临时参考),事件控制块(ECB),uC/OS-II 使用ECB的数据结构统一描述三类事件(信号量、消息邮箱、消息队列)。 uC/OS-II 中的ECB数据结构如下:,typedef struct IN

6、T8U OSEventType;/事件类型 INT16U OSEventCnt;/计数信号量的计数器 void * OSEventPtr;/消息(消息队列)指针 INT8U OSEventGrp;/等待事件的任务组 INT8U OSEventTblOS_EVENT_TBL_SIZE; /任务等待表 OS_EVENT;,14,8.00 建立一个互斥型信号量,OSMutexCreate(),创建互斥型信号量,调用系统函数OSMutexCreate( )创建互斥型信号量,其原型如下:,OS_EVENT * OSMutexCreate( INT8U prio,/信号量优先级别 INT8U *err/函

7、数结果状态信息 );,函数操作说明:该函数从空事件控制块队列(OSEventFreeList)获得一个ECB,并将其初始化(初始化后的数据情况见前页插图);用户查看 *err 可知道本函数的执行结果(OS_NO_ERR);用户通过本函数返回的事件指针来使用该 “信号” 。,15,信号量及其操作-(临时参考),信号量的操作 - 创建信号量,信号量操作系统函数定义在 OS_SEM.C 文件。 在使用信号量之前,必须创建信号量。 创建信号量系统函数的原型:,OS_EVENT * OSSemCreate( INT16U cnt/信号量计数初值 ),功能:从OSEventFreeList中申请一个ECB

8、,并进行初始化(用cnt初始化ECB(Sem)-OSEventCnt);返回一个已初始化的 ECB 的指针。,16,创建互斥型信号量,调用系统函数OSMutexCreate( )创建互斥型信号量注意事项:,1、不支持在ISR中创建互斥信号量;否则,创建失败且返回出错信息 *err = OS_ERR_CREATE_ISR 2、指定的互斥信号量优先级不能与其它任务冲突;否则,创建失败且返回出错信息 *err = OS_PRIO_EXIST 3、指定的优先级要合法,否则,创建失败且返回出错信息 *err = OS_PRIO_INVALID 4、如果信号量创建失败,创建函数返回事件的指针为空(即 =

9、Null) 5、正确创建了互斥信号量,函数返回一个 ECB 指针,且 *err = OS_NO_ERR,17,OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif OS_EVENT *pevent; if (OSIntNesting 0) /* See if called from ISR . */ *err = OS_ERR_CREATE_ISR; /*

10、 . cant CREATE mutex from an ISR */ return (OS_EVENT *)0); #if OS_ARG_CHK_EN 0 if (prio = OS_LOWEST_PRIO) /* Validate PIP */ *err = OS_PRIO_INVALID; return (OS_EVENT *)0); #endif,18,OS_ENTER_CRITICAL(); if (OSTCBPrioTblprio != (OS_TCB *)0) /* Mutex priority must not already exist */ OS_EXIT_CRITICAL

11、(); /* Task already exist at priority . */ *err = OS_PRIO_EXIST; /* . inheritance priority */ return (OS_EVENT *)0); OSTCBPrioTblprio = (OS_TCB *)1; /* Reserve the table entry */ pevent = OSEventFreeList; /* Get next free event control block */ if (pevent = (OS_EVENT *)0) /* See if an ECB was availa

12、ble */ OSTCBPrioTblprio = (OS_TCB *)0; /* No, Release the table entry */ OS_EXIT_CRITICAL(); *err = OS_ERR_PEVENT_NULL; /* No more event control blocks */ return (pevent); ,OSEventFreeList = (OS_EVENT *)OSEventFreeList-OSEventPtr; /* Adjust the free list */ OS_EXIT_CRITICAL(); pevent-OSEventType = O

13、S_EVENT_TYPE_MUTEX; pevent-OSEventCnt = (prio OSEventPtr = (void *)0; /* No task owning the mutex */ OS_EventWaitListInit(pevent); *err = OS_NO_ERR; return (pevent); ,0 x00FF,8.01 删除一个互斥型信号量,OSMutexDel(),删除互斥型信号量,可以调用系统函数OSMutexDel( )函数删除不再使用的互斥信号量;其原型如下:,OS_EVENT * OSMutexDel( OS_EVENT * pevent ,/信

14、号量指针 INT8U opt,/删除方式选项 INT8U *err/函数结果状态信息 );,备注:函数返回删除事件的 “事件指针” ;当删除一个不存在的事件时,返回 Null 。,21,删除互斥型信号量,系统函数OSMutexDel( )删除互斥型信号量注意事项:,1、opt 参数含义:,2、返回信息 *err 的含义:,OS_NO_ERR Mutex删除成功; OS_ERR_DEL_ISR 不允许在ISR中进行删除 OS_ERR_INVALID_OPT 删除方式参数非法 OS_ERR_TASK_WAITING 还有等待该信号的任务 OS_ERR_EVENT_TYPE 指定的事件不是Mutex

15、 OS_ERR_PEVENT_NULL 事件指针为空,OS_DEL_NO_PEND - 无申请等待任务时方删除。 OS_DEL_ALWAYS - 无条件直接删除,所有的等待任务皆转 入到ready 状态。,22,OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif BOOLEAN tasks_waiting; INT8U pip

16、; if (OSIntNesting 0) /* See if called from ISR . */ *err = OS_ERR_DEL_ISR; /* . cant DELETE from an ISR */ return (pevent); ,#if OS_ARG_CHK_EN 0 if (pevent = (OS_EVENT *)0) /* Validate pevent */ *err = OS_ERR_PEVENT_NULL; return (OS_EVENT *)0); if (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Vali

17、date event block type */ *err = OS_ERR_EVENT_TYPE; return (pevent); #endif OS_ENTER_CRITICAL(); if (pevent-OSEventGrp != 0 x00) /* See if any tasks waiting on mutex */ tasks_waiting = TRUE; /* Yes */ else tasks_waiting = FALSE; /* No */ ,switch (opt) case OS_DEL_NO_PEND: /* Delete mutex only if no t

18、ask waiting */ if (tasks_waiting = FALSE) pip = (INT8U)(pevent-OSEventCnt 8); OSTCBPrioTblpip = (OS_TCB *)0; /* Free up the PIP */ pevent-OSEventType = OS_EVENT_TYPE_UNUSED; pevent-OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; OS_EXIT_CRITICAL(

19、); *err = OS_NO_ERR; return (OS_EVENT *)0); /* Mutex has been deleted */ else OS_EXIT_CRITICAL(); *err = OS_ERR_TASK_WAITING; return (pevent); ,case OS_DEL_ALWAYS: /* Always delete the mutex */ while (pevent-OSEventGrp != 0 x00) /* Ready ALL tasks waiting for mutex */ OS_EventTaskRdy(pevent, (void *

20、)0, OS_STAT_MUTEX); pip = (INT8U)(pevent-OSEventCnt 8); OSTCBPrioTblpip = (OS_TCB *)0; /* Free up the PIP */ pevent-OSEventType = OS_EVENT_TYPE_UNUSED; pevent-OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ OSEventFreeList = pevent; /* Get next free event control block */

21、 OS_EXIT_CRITICAL(); if (tasks_waiting = TRUE) /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ *err = OS_NO_ERR; return (OS_EVENT *)0); /* Mutex has been deleted */,default: OS_EXIT_CRITICAL(); *err = OS_ERR_INVALID_OPT; return (pevent); ,8.02

22、等待一个互斥型信号量(挂起),OSMutexPend(),请求互斥型信号量,当任务要访问一个独占共享资源时,要先调用系统函数OSMutexPend( )函数申请相应的互斥信号量;其原型如下:,void OSMutexPend( OS_EVENT * pevent ,/信号量指针 INT16U timeout,/等待时间 INT8U *err/函数结果状态信息 );,28,信号量及其操作-(临时参考),信号量的操作 - 请求信号量,请求信号量系统函数的原型:,void OSSemPend( OS_EVENT * pevent, /信号量指针指示申请目标 INT16U timeout, /等待限时

23、,OS Tick 数 INT8U *err ); /函数执行情况,备注:参数 timeout 用于约定本任务等待申请信号量的时限,单位是Tick;当等待超时时,本任务被uC/OS-II直接转入就续状态。当该参数为 0 时,含义为无限时等待。通过查阅 *err 参数可知函数的执行情况。,操作:如果信号量有效( ECB(Sem)-OSEventCnt 0),则OSEventCnt-,本任务goon;否则,将申请的事件的ECB-OSEventGrp及OSEventTbl 相应位置1,本Task转入Wait状态并执行OS_Sched( )。,29,请求互斥型信号量,调用系统函数OSMutexPend(

24、 )申请互斥型信号量注意事项:,1、不支持在ISR中申请互斥信号量;否则,申请失败且返回出错信息 *err = OS_ERR_PEND_ISR 2、申请的互斥信号量必须存在;否则,申请失败且返回出错信息 *err = OS_ERR_PEVENT_NULL 3、指定的事件须是互斥信号量,否则,申请失败且返回出错信息 *err = OS_ERR_EVENT_TYPE 4、申请到了互斥信号量,*err = OS_NO_ERR 5、如果信号量未申请到,本任务则进入 “等待” 状态。,30,void OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U

25、 *err) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif INT8U pip; /* Priority Inheritance Priority (PIP) */ INT8U mprio; /* Mutex owner priority */ BOOLEAN rdy; /* Flag indicating task was ready */ OS_TCB *ptcb; if (OSIntNesting 0) /* See if called

26、from ISR . */ *err = OS_ERR_PEND_ISR; /* . cant PEND from an ISR */ return; ,#if OS_ARG_CHK_EN 0 if (pevent = (OS_EVENT *)0) /* Validate pevent */ *err = OS_ERR_PEVENT_NULL; return; if (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Validate event block type */ *err = OS_ERR_EVENT_TYPE; return; #endi

27、f,OS_ENTER_CRITICAL(); /* Is Mutex available? */ if (INT8U)(pevent-OSEventCnt /* Point to TCB of mutex owner */,if (ptcb-OSTCBPrio != pip ,if (rdy = TRUE) /* If task was ready at owners priority .*/ OSRdyGrp |= ptcb-OSTCBBitY; /* . make it ready at new priority. */ OSRdyTblptcb-OSTCBY |= ptcb-OSTCBB

28、itX; OSTCBPrioTblpip = (OS_TCB *)ptcb; OSTCBCur-OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */ OSTCBCur-OSTCBDly = timeout; /* Store timeout in current tasks TCB */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); OS_Sched(); /*

29、 Find next highest priority task ready */ OS_ENTER_CRITICAL();,if (OSTCBCur-OSTCBStat ,8.03 释放一个互斥型信号量,OSMutexPost(),调用系统函数OSMutexPost( )发送(释放)互斥型信号量,其原型如下:,INT8U OSMutexPost( OS_EVENT * pevent /信号量指针 );,37,发送互斥型信号量,调用系统函数OSMutexPost( )释放互斥型信号量注意事项:,1、不支持在ISR中释放互斥信号量;否则释放失败且函数返回OS_ERR_POST_ISR 2、释放的

30、互斥信号量必须存在;否则释放失败且函数返回OS_ERR_PEVENT_NULL 3、释放的事件要是互斥信号量,否则释放失败且函数返回OS_ERR_EVENT_TYPE 4、只能释放自己的信号,否则释放失败且函数返回OS_ERR_NOT_MUTEX_OWNER 5、正确释放了互斥信号量,函数返回 OS_NO_ERR,38,INT8U OSMutexPost (OS_EVENT *pevent) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif INT

31、8U pip; /* Priority inheritance priority */ INT8U prio; if (OSIntNesting 0) /* See if called from ISR . */ return (OS_ERR_POST_ISR); /* . cant POST mutex from an ISR */ #if OS_ARG_CHK_EN 0 if (pevent = (OS_EVENT *)0) /* Validate pevent */ return (OS_ERR_PEVENT_NULL); if (pevent-OSEventType != OS_EVE

32、NT_TYPE_MUTEX) /* Validate event block type */ return (OS_ERR_EVENT_TYPE); #endif,OS_ENTER_CRITICAL(); pip = (INT8U)(pevent-OSEventCnt 8); /* Get priority inheritance priority of mutex */ prio = (INT8U)(pevent-OSEventCnt ,if (OSTCBCur-OSTCBPrio = pip) /* Did we have to raise current tasks priority?

33、*/ /* Yes, Return to original priority */ /* Remove owner from ready list at pip */ if (OSRdyTblOSTCBCur-OSTCBY ,OSTCBPrioTblpip = (OS_TCB *)1; /* Reserve table entry */ if (pevent-OSEventGrp != 0 x00) /* Any task waiting for the mutex? */ /* Yes, Make HPT waiting for mutex ready */ prio = OS_EventT

34、askRdy(pevent, (void *)0, OS_STAT_MUTEX); pevent-OSEventCnt ,8.04 无等待地获取互斥型信号量(任务不挂起),OSMutexAccept(),如果要得到mutex,而当前mutex无效,那么不让任务进入休眠态也是可以的。,43,INT8U OSMutexAccept (OS_EVENT *pevent, INT8U *err) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif if (O

35、SIntNesting 0) /* Make sure its not called from an ISR */ *err = OS_ERR_PEND_ISR; return (0); #if OS_ARG_CHK_EN 0 if (pevent = (OS_EVENT *)0) /* Validate pevent */ *err = OS_ERR_PEVENT_NULL; return (0); if (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Validate event block type */ *err = OS_ERR_EVEN

36、T_TYPE; return (0); #endif,OS_ENTER_CRITICAL(); /* Get value (0 or 1) of Mutex */ if (pevent-OSEventCnt ,8.05 获取互斥型信号量的当前状态,OSMutexQuery(),应用程序可看到用于互斥型信号量mutex的事件控制块的当前状况。,46,INT8U OSMutexQuery (OS_EVENT *pevent, OS_MUTEX_DATA *pdata) #if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status reg

37、ister */ OS_CPU_SR cpu_sr; #endif INT8U *psrc; INT8U *pdest; if (OSIntNesting 0) /* See if called from ISR . */ return (OS_ERR_QUERY_ISR); /* . cant QUERY mutex from an ISR */ #if OS_ARG_CHK_EN 0 if (pevent = (OS_EVENT *)0) /* Validate pevent */ return (OS_ERR_PEVENT_NULL); if (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Validate event block type */ return (OS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论