




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第7章 任务的同步与通信信号量集/事件标志组用于任务与多个事件同步主要内容 信号量机制 互斥型信号量 信号量集机制(事件标制组) 消息邮箱 消息队列在实际应用中,任务常常需要与多个事件同步,即要根据多个信号量组合作用的结构来决定任务的运行方式发信号任务请求信号的任务AND/OR 信号量集作用置位和清除独立型(或)同步关联型(与)同步l 信号量集的数据结构l 信号量集操作l 信号量集的操作 信号量集的结构c/os-II的信号量集由两部分组成:第一部分叫做标志组,其中存放了信号量集中的所有信号;第二部分叫做等待任务链表,链表中的每个节点都对应一个正在等待信号量集的等待任务,信号量集根据这个链表来管
2、理等待任务。事件标志组的数据结构 OS_FLAG_GRP:typedef struct INT8U OSFlagType; /* 设置为OS_EVENT_TYPE_FLAG类型 */ void *OSFlagWaitList; /* 指向等待任务链表的指针 */ OS_FLAGS OSFlagFlags; /*事件标志状态的位,可以是 8位, 16位 或 32位 */ OS_FLAG_GRP; 信号量集图示指向等待任务链表OS_EVENT_TYPE_FLAG1/01/01/01/01/01/0 1/01/0每一位都表示一个信号的状态OSFlagTypeOSFlagWaitListOSFlagF
3、lags在文件OS_CFG.H中来定义位数,8、16、32OS_EVENT_TYPE_FLAGOSFlagWaitListOSFlagFlagsOS_EVENT_TYPE_FLAGOSFlagWaitListOSFlagFlagsOS_EVENT_TYPE_FLAGOSFlagWaitListOSFlagFlagsOSFlagFreeList共OS_MAX_FLAGS个空标志组 空信号量集标志组表链表在文件OS_CFG.H中来定义等待任务链表 OS_FLAG_NODE的代码如下:typedef struct void *OSFlagNodeNext; /* 指向下一个节点的指针 */ void
4、 *OSFlagNodePrev; /* 指向前一个节点的指针 */ void *OSFlagNodeTCB; /* 指向对应任务的任务控制块的指针 */ void *OSFlagNodeFlagGrp; /* 反向指向事件标志组的指针 */ OS_FLAGS OSFlagNodeFlags; /*信号过滤器 */ INT8U OSFlagNodeWaitType; /*定义逻辑运算关系*/ OS_FLAG_NODE;OSFlagTypeOSFlagWaitListOSFlagFlags标志组OSFlagNodeFlagGrpOSFlagNodeNextOSFlagNodePrevOSFlag
5、NodeTCBOSFlagNodeFlagsOSFlagNodeWaitTypeOSFlagNodeFlagGrpOSFlagNodeNextOSFlagNodePrevOSFlagNodeTCBOSFlagNodeFlagsOSFlagNodeWaitTypeOSFlagNodeFlagGrpOSFlagNodeNextOSFlagNodePrevOSFlagNodeTCBOSFlagNodeFlagsOSFlagNodeWaitType0OSTCBFlagNode.OSTCBFlagNode.OSTCBFlagNode.OS_TCBOS_TCBOS_TCB等待任务链表0信号量集结构图1/0
6、1/01/01/01/01/01/01/01/01/01/01/01/01/01/01/0OSFlagFlags发送任务量级的任务OSFlagNodeFlags1/0?AND/OR?请求信号量级的任务OSFlagNodeWaitType信号量集对信号的逻辑运算及控制置位或清除OSFlagNodeNextOSFlagNodePrevOSFlagNodeTCBOSFlagNodeFlagGrp10001001OS_FLAG_CLR_ALL指向前一个节点回指OS_FLAG_GRP结构OSFlagNodeFlagsOSFlagNodeWaiteType指向下一个节点指向等待任务的任务控制块举例:信号量
7、集等待任务链表的一个节点等待信号量集的第0、3、7位都清0l 信号量集的数据结构l 对等待任务链表的操作l 信号量集的操作添加节点删除节点添加节点给等待任务链表添加节点的函数为OS_FlagBlock( )。该函数的原型如下:static void OS_FlagBlock( OS_FLAG_GRP *pgrp, /信号量集指针 OS_FLAG_NODE *pnode, /待添加的等待任务节点指针 OS_FLAG_flags, /指定等待信号的数据 INT8U wait_type, /信号与等待任务之间的逻辑 INT16U timeout /等待时限 );这个函数将在请求信号量集函数OSFla
8、gPend( )中被调用。删除节点从等待任务链表中删除一个节点的函数为OS_FlagUnlink( )。该函数原型如下:void OS_FlagUnlink (OS_FLAG_NODE *pnode);这个函数将在发送信号量集函数OSFlagPost( )中被调用。l 信号量集的数据结构l 信号量集操作l 信号量集的操作信号量集的操作函数OSFlagCreat()OSFlagAccept()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagQuery()建立一个事件标志组,OSFlagCreate()OSFlagCreat()的函数原型如下:OS_FLAG_GR
9、P *OSFlagCreat(OS_FLAGS flags,INT8U *err); 参数:flags::事件标志组的事件标志初值;err:指向错误代码的指针。出错代码为以下值之一。OS_NO_ERR 成功创建事件标志组。OS_ERR_CREAT_ISR 从中断中调用OSFlagCreat()函数。OS_FLAG_GRP_DEPLETED 系统没有剩余的空闲事件标志组,需要更改OS_CFG.H中的系统事件标志组数目的配置 返回值:如果成功创建事件标志组,则返回该事件标志组的指针。如果系统没有剩余的空闲事件标志组,则返回空指针。创建信号量集的函数主要做了两项工作: 一是从空标志组链表中取下一个标
10、志组,并同时给成员OSFlagType和OSFlagFlags赋初值; 二是令指向等待任务链表的指针OSFlagWaitList为空指针。 在实际应用中,OSFlagFlags可以根据需要赋值。typedef struct INT8U OSFlagType; void *OSFlagWaitList; OS_FLAGS OSFlagFlags; OS_FLAG_GRP;信号量集的操作函数OSFlagCreat()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagAccept()OSFlagQuery()删除一个事件标志组,OSFlagDel()OSFlagDel
11、()函数原型如下:OS_FLAG_GRP *OSFlagDel(OS_FLAG_GPR pgrg,INT8U opt,INT8U *err); 参数:pgrp:指向事件标志组的指针;opt:指明是仅在没有任务等等事件标志组时删除该事件标志组(OS_DEL_NO_PEND),还是不管是否有任务等待事件标志组都删除该事件标志组(OS_DEL_ALWAYS)。如果是后者,所有等待该事件标志组的任务都被置为就绪。err:指向错误代码的指针。出错代码为以下值之一: OS_NO_ERR 成功删除事件标志组。 OS_ERR_DEL_ISR 从中断中调用OSFlagDel()函数。 OS_FLAG_INVAL
12、ID_PGRP pgrp是空指针。 OS_ERR_EVENT_TYPE pgrp不是指向事件标志组的指针。 OS_ERR_INVALID_OPT opt参数不是指定的值。 OS_ERR_TASK_WAITING 如果opt参数为OS_DEL_NO_PEND,那么此时有任务等待事件标志组。 返回值:如果事件标志组被删除,则返回空指针;如果没有删除,则仍然返回指向该事件标志组的指针。在后一种情况下,需要检查出错代码,找出事件标志组没有成功删除的原因。信号量集的操作函数OSFlagCreat()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagAccept()OSFl
13、agQuery() 请求信号量集OSFlagPend( )任务可以通过调用函数OSFlagPend( )请求一个信号量集。该函数的原型如下:OS_FLAGS OSFlagPend( OS_FLAG_GRP *pgrp, /所请求的信号量集指针 OS_FLAGS flags, /滤波器 INT8U wait_type, /逻辑运算类型 INT16U timeout, /等待时限 INT8U *err /错误信息 );typedef struct void *OSFlagNodeNext; void *OSFlagNodePrev; void *OSFlagNodeTCB; void *OSFla
14、gNodeFlagGrp; OS_FLAGS OSFlagNodeFlags; INT8U OSFlagNodeWaitType; OS_FLAG_NODE;OS_FLAG_WAIT_CLR_ALL,所有指定事件标志位清0。OS_FLAG_WAIT_CLR_ANY,任意指定事件标志位清0。OS_FLAG_WAIT_SET_ALL,所有指定事件标志位置位。OS_FLAG_WAIT_SET_ANY,任意指定事件标志位置位。举例例如,等待信号OSFlagFlags中的第0位和第3位置1,则调用时的代码如下:OS_FLAGS OSFlagPend( FlagPtr, /信号量集指针 (OS_FLAGS
15、)9, /选择所要等待的信号 OS_FLAG_WAIT_SET_ALL, /等所指定位都置1 &err /错误信息 );err:指向出错代码的指针,出错代码为以下值之一。 OS_NO_ERR 成功调用。 OS_ERR_PEND_ISR 从中断中调用该函数,这是规则不允许的。 OS_FLAG_INVALID_PGRP pgrp是空指针。 OS_ERR_EVENT_TYPE pgrp不是指向事件标志组的指针。 OS_TIMEOUT 等待事件标志组的事件标志超时。 OS_FLAG_ERR_WAIT_TYPE wait_type不是指定的参数值之一。 返回值:返回OSFlagPend()函数允许结束后
16、的事件标志组事件标志状态;如果发生了超时,则返回0。信号量集的操作函数OSFlagCreat()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagAccept()OSFlagQuery()向信号量集发信号任务可以通过调用函数OSFlagPost( )向信号量集发信号。该函数的原型如下:OS_FLAGS OSFlagPost( OS_FLAG_GRP *pgrp, /信号量集指针 OS_FLAGS flags, /选择所要发送的信号 INT8U opt, /信号有效的选项 INT8 *err /错误信息 );typedef struct INT8U OSFlagT
17、ype; void *OSFlagWaitList; OS_FLAGS OSFlagFlags; OS_FLAG_GRP;置位、复位举例例如,要对信号量集FlagPtr发送信号,待发送的信号为OSFlagFlags中的第0位和第3位并且是要把它们置1,则调用时的代码如下:OS_FLAGS OSFlagPost( FlagPtr, /信号量集指针 (OS_FLAGS)9, /选择所要发送的信号 OS_FLAG_SET, /信号有效的选项 &err /错误信息 ); 设置为0:OS_FLAG_CLROSFlagPost()err:指向出错代码的指针,出错代码为以下值之一。OS_NO_ERR 成功调
18、用。OS_FLAG_INVALID_PGRP pgrp是空指针。OS_ERR_EVENT_TYPE pgrp不是指向事件标志组的指针。OS_ERR_INVALID_OPT opt参数不是指定的值。 返回值:事件标志组的新的事件标志状态。信号量集的操作函数OSFlagCreat()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagAccept()OSFlagQuery()无等待地获得信号量集,OSFlagAccept()OSFlagAccept()函数原型如下:OS_FLAGS OSFlagAccept(OS_FLAG_GRP *pgrp,OS_FLAGS fla
19、gs,INT8U wait_type, INT8U *err); 参数:pgrp:指向事件标志组的指针。flags:指定需要检查的事件标志位。wait_type:定义等待事件标志位的方式。可以定义为以下4种方式之一: OS_FLAG_WAIT_CLR_ALL,所有指定事件标志位清0。 OS_FLAG_WAIT_CLR_ANY,任意指定事件标志位清0。 OS_FLAG_WAIT_SET_ALL,所有指定事件标志位置位。 OS_FLAG_WAIT_SET_ANY,任意指定事件标志位置位。 如果需要在得到期望的事件标志后,恢复该事件标志,则可以在调用函数时,将该参数加上一个常量OS_FLAG_CON
20、SUME。err:指向出错代码的指针,出错代码为以下值之一。 OS_NO_ERR 成功调用。 OS_ERR_EVENT_TYPE pgrp不是指向事件标志组的指针。 OS_FLAG_ERR_WAIT_TYPE wait_type参数不是指定的4种方式之一。 OS_FLAG_INVALID_PGRP pgrp是空指针。 OS_FLAG_ERR_NO_RDY 指定的事件标志没有发生。 返回值:返回事件标志组的事件标志状态信号量集的操作函数OSFlagCreat()OSFlagDel()OSFlagPend()OSFlagPost()OSFlagAccept()OSFlagQuery()查询事件标志
21、组的状态,OSFlagQuery()OSFlagQuery()函数原型如下:OS_FLAGS OSFlagQuery(OS_FLAG_GRP *pgrp, INT8U *err); 参数:pgrp:指向事件标志组的指针。err:指向出错代码的指针,出错代码为以下值之一。 OS_NO_ERR 成功调用。 OS_FLAG_INVALID_PGRP pgrp是空指针。 OS_ERR_EVENT_TYPE pgrp不是指向事件标志组的指针。返回值:返回事件标志组的事件标志状态l 信号量集的数据结构l 信号量集操作l 信号量集的操作l 举例举例 设计一个有三个任务的应用程序,这三个任务分别叫做MyTas
22、k、YouTask和HerTask。要求用一个信号量集来控制MyTask的运行,即任务YouTask发送一个信号,任务HerTask发送一个信号,当这两个任务都发了信号之后,MyTask才能运行。/*Test*/#include “includes.h”#define TASK_STK_SIZE 512 /任务堆栈长度#define N_MESSAGES 128 /定义消息队列长度OS_STK StartTaskStkTASK_STK_SIZE; /定义任务堆栈区OS_STK MyTaskStkTASK_STK_SIZE; /定义任务堆栈区OS_STK YouTaskStkTASK_STK_S
23、IZE; /定义任务堆栈区OS_STK HerTaskStkTASK_STK_SIZE; /定义任务堆栈区INT16S key; /用于退出的键char *s1=“MyTask正在运行”; char *s2=“YouTask正在运行”;char *s3=“HerTask正在运行”;INT8U err;INT8U y=0; /字符显示位置OS_FLAG_GRP *Sem_F; void StartTask(void *data); /声明起始任务void MyTask(void *data); /声明任务void YouTask(void *data); /声明任务void HerTask(vo
24、id *data); /声明任务/*主函数*/void main(void) OSInit(); /初始化c/os-II PC_DOSSaveReturn( ); /保存DOS环境 PC_VectSet(uCOS,0SCtxSw); /安装c/os-II中断 Sem_F=OSFlagCreate(0,&err); /创建信号量集 OSTaskCreate(StartTask, /创建任务StartTask (void *)0, /给任务传递参数 &StartTaskStkTASK_STK_SIZE-1, /设置任务堆栈栈顶指针 0); /使任务的优先级别为0 OSStart(); /启动多任务
25、管理/*任务StartTask*/void StartTask(void *pdata)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif pdata=pdata; OS_ENTER_CRITICAL( ); PC_VectSet(0 x08,OSTickISR); /安装时钟中断向量 PC_SetTickRate(OS_TICKS_PER_SEC); /设置c/os-II时钟频率 OS_EXIT_CRITICAL( ); OSStatInit(); /初始化统计任务 OSTaskCreate(MyTask, (void *)0, &MyTaskS
26、tkTASK_STK_SIZE-1, 3); OSTaskCreate(YouTask, (void *)0, &YouTaskStkTASK_STK_SIZE-1, 4); OSTaskCreate(HerTask, (void *)0, &HerTaskStkTASK_STK_SIZE-1, 5); for( ; ; ) /如果按下ESC键,则退出c/os-II if(PC_GetKey(&key)=TRUE) if(key=0 x1B) PC_DOSReturn(); OSTimeDlyHMSM(0,0,3,0); /等待3s /*任务MyTask*/void MyTask(void *
27、pdata)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif pdata=pdata; for( ; ; ) OSFlagPend(Sem_F, (OS_FLAGS)3, OS_FLAG_WAIT_SET_ALL, 0, &err ); PC_DispStr(10,+y, s1, DISP_BGND_BLACK+DISP_FGND_WHITE); OSTimeDlyHMSM(0,0,2,0); /等待2s /*任务YouTask*/void YouTask(void *pdata)#if OS_CRITICAL_METHOD=3 OS_CPU_S
28、R cpu_sr;#endif pdata=pdata;for( ; ; ) PC_DispStr(10,+y, s2, DISP_BGND_BLACK+DISP_FGND_WHITE); OSTimeDlyHMSM(0,0,8,0); /等待8s OSFlagPost(Sem_F, (OS_FLAGS)2, OS_FLAG_SET, 0, &err ); OSTimeDlyHMSM(0,0,2,0); /等待2s /*任务HerTask*/void HerTask(void *pdata)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif pda
29、ta=pdata;for( ; ; ) PC_DispStr(10,+y, s3, DISP_BGND_BLACK+DISP_FGND_WHITE); OSTimeDlyHMSM(0,0,8,0); /等待8s OSFlagPost( Sem_F, (OS_FLAGS)1, OS_FLAG_SET, &err ); OSTimeDlyHMSM(0,0,1,0); /等待1s /*END*/进一步把前例中任务把前例中任务MyTask调用的请求信调用的请求信号量集函数号量集函数OSFlagPend( )改为无等待请改为无等待请求函数求函数OSFlagAccept( ),运行该程序后,运行该程序后,观察运行结果并与前例应用程序的运观察运行结果并与前例应用程序的运行结果进行比较。行结果进行比较。任务MyTask修改后的代码如下:/*任务MyTask*/void MyTask(void *pdata)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif pdata=pdatafor( ; ; ) OSFlagAccept(Sem_F, (OS_FLAGS)3, OS_FLAG_WAIT_SET_ALL, &err );PC_DispStr(10,+y, s1, DISP_BGND_BLACK+DIS
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 股东承担债务协议书范本
- 经销商商合同终止协议书
- 甲醇燃料灶安全协议合同
- 销售烟气喷淋泵合同范本
- 私人购买企业股份协议书
- 燃气委托执法协议书范本
- 绿化苗木劳务分包协议书
- 网络售货服务合同协议书
- 米糊或米粉批发合同范本
- 食堂财产交接协议书范本
- 基础会计-中职课件
- 小学生防性侵安全知识讲座
- 《软件项目质量管理》课件
- GB/T 3211-2023金属铬
- 芯烨xp q200驱动及使用说明机功能设置
- 华为公司渠道政策
- 人教版三年级上册数学(全册)同步练习题及答案-人教三年级数学全册练习题及答案
- 《湖南省医疗保险“双通道”管理药品使用申请表》
- 海利普变频器C系列中文说明书
- 人教版八年级(上册)物理习题全集(附答案)
- 义务教育历史课程标准(2022年版)
评论
0/150
提交评论