信号量集:实现多个信号量组合作用的功能,用于多个任务同步机制
信号量集的组成:
标志组:存放信号量集中的所有信号
OS_FLAG_GRP的结构:
typedef struct{
INT8U OSFlagType; //信号量集的标识
void *OSFlagWaitList;//指向等待任务链表的指针
OS_FLAGS OSFlagFlags; //所有信号列表
}OS_FLAG_GRP;
各变量的含义:
OSFlagType:信号量集的标识,该成员变量的值应该固定为OS_EVENT_TYPE_FLAG。
OSFlagFlags:OS_FLAGS类型的变量,该变量用来存放信号量集所有信号的状态,每个信号占据一个二进制位。信号量集中可以存放多少个信号,取决于OSFlagFlags的长度。这个长度可以根据应用程序需要信号的数目定义为8位、16位、32位。
OSFlagWaitList:当一个信号量集被创建后,这个指针指向了这个信号量集的等待任务链表。
在UC/OS-II初始化时,系统会根据在文件OS_CFG.H中定义的常数0S_MAX_FLAGS,来创建0S_MAX_FLAGS个标志组(信号量集),并借用成员OSFlagWaitList作为指针把这些标志组链接成一个单向链表。由于这个链表中的各个标志组还未被真正创建,因此叫做空标志组链表
等待任务链表:链表中的每个节点都对应一个正在等待信号量集的等待任务
信号量集用一个双向链表来组织等待任务,每一个等待任务都是该链表的一个节点(Node)。标志组OS_FLAG_GRP的成员OSFlagWaitList就指向了信号量集的这个等待任务链表。
等待任务链表节点OS_FLAG_NODE的结构:
typedef struct {
void *OSFlagNodeNext; //指向下一个节点的指针
void *OSFlagNodePrev; //指向前一个节点的指针
void *OSFlagNodeTCB; //指向对应任务的任务控制块
void *OSFlagNodeFlagGrp; //反向指向信号量集指针
OS_FLAGS OSFlagNodeFlags; //信号过滤器
INT8U OSFlagNodeWaitType; //定义逻辑运算关
//系的数据
}
OSFlagNodeFlagGrp:反向指向信号量集标志组的指针,是在等待任务链表中删除一个节点或添加一个节点时用到的指针。
OSFlagNodeTCB:指向等待任务TCB的指针,信号量集的等待任务链表通过这个指针把链表节点与等待任务关联起来。
OSFlagNodeFlags:利用它可在标志组成员OSFlagNodeFlags的信号中只把请求任务需要的信号筛选出来,而把其它的信号屏蔽掉。也就是说,一个请求信号量集的任务可以需要信号集的所有信号,也可以只需要其中的部分信号,它究竟需要那些信号,要通过在成员OSFlagNodeFlags中与所等待信号对应的二进制位进行置1来指定,而任务不需要的信号的位置0.
OSFlagNodeWaitType:指定逻辑关系,它有四个常数可以选择。它们既指定了逻辑关系,也指定了信号的有效状态。
信号集的函数
生成信号集
OS_FLAG_GRP *OSFlagCreate(
OS_FLAGS flags,//信号的初始值
INT8U *err //错误信息
)
主要的工作:
(1)从空标志组链表中取下一个标志组,并同时给成员OSFlagType和OSFlagFlags赋初值;
(2)令指向等待任务链表的指针OSFlagWaitList为空指针
请求信号集
函数: OSFlagPend()
原型:
OS_FLAGS OSFlagPend(
OS_FLAG_GRP *pgrp, // 请求信号量集指针
OS_FLAGS flags , // 滤波器
INT8U wait_type, // 逻辑运算类型
INT16U timeout, // 等待时限
INT8U *err // 错误信息
);
返回值:调用成功后返回标志组成员OSFlagFlags的值。也就是信号的状态
任务也可以通过调用函数OSFlagAccept()无等待地请求一个信号量集。
原型:
OS_FLAGS OSFlagPend(
OS_FLAG_GRP *pgrp, //请求信号量集指针
OS_FLAGS flags, //滤波器
INT8U wait_type, //逻辑运算类型
INT v *err //错误信息
);
任务可以通过调用函数OSFlagPost()向信号量集发信号。
函数原型:
OS_FLAGS OSFlagPost(
OS_FLAG_GRP *pgrp, // 请求信号量集指针
OS_FLAGS flags, // 选择所要发送的信号
INT8U opt, // 信号有效的选项
INT v *err // 错误信息
);
说明:所谓任务向信号量集发信号,就是对信号量集标志组中的信号进行置1或者置0的操作。至于对信号量集中的那些信号进行操作,由函数的参数flags决定;对指定的信号是置1还是置0,有参数opt决定(opt = OS_FLAG_SET为置1;opt = OS_FLAG_CLR为置0操作)。
函数OSFlagQuery()查询一个信号量集的状态。
原型:
OS_FLAGS OSFlagQuery (
OS_FLAG_GRP *pgrp, //待查询的信号量集的指针
INT v *err //错误信息
);
返回值:被查询信号量集标志组的成员OSFlagFlags,应用程序可以用它来完成一些更为复杂的操作。