信号量、信号量的操作(创建信号量、请求信号量、发送信号量、删除信号量、查询信号量的状态)
4.2信号量及其操作
4.2.1信号量
(1)当事件控制块成员OSEventType的值被设置为OS_EVENT_TYPE_SEM时,这个事件控制块描述的就是一个信号量。
(2)信号量是由信号量计数器和任务等待表两部分组成。
(3)每当有任务申请信号量时,
如果信号量计数器OS_EventCnt() > 0,OSEventCnt – 1,任务继续运行;
OS_EventCnt() == 0, OSEventCnt = 0,任务列入等待表;
如果正在使用信号量的任务释放了该信号量,就会在任务等待表中找出优先级别最高的等待任务,并在使它就绪后调用调度器引发一次调度;
如果任务等待表汇总没有等待任务,信号量+ 1;
4.2.2信号量的操作
1.创建信号量
在使用信号量之前,应用程序必须调用函数OSSemCreate()来创建一个信号量。
函数原型:
OS_EVENT *OSSemCreate(
INT16U cot //信号量计数器初值
);
返回值为已创建的信号量的指针。
2.请求信号量
(1)任务通过调用函数OSSemPend()请求信号量,函数原型:
void OSSemPend(
OS_EVNET *pevent, //信号量的指针
INT16U timeout, //等待时限
INT8U *err //错误信息
);
参数pevent是被请求信号量的指针。
timeout:任务等待时间限制,超过该时间可以结束等待状态而进入就绪状态。
timeout = 0时,等待时间无限长。
err:调用成功后值为OS_NO_ERR,失败则会根据出现的具体错误产生不同的值。
(2)访问共享资源时,先请求管理该资源的信号量,根据信号量是否有效决定该任务是否可以继续运行。
(3)如果希望在信号量无效时准许任务不进入等待状态而继续运行,则不用函数OSSemPend(),而是调用函数OSSemAccept()来请求信号量。
3.发送信号量
(1)释放信号量也叫发送信号量;
(2)发送信号量必须调用函数OSSemPost():
该函数对信号量计数器操作之前,先检查是否还有等待该信号量的任务;
没有—>OSEvemtCnt + 1;
有 -->调度器OS_Sched()运行等待任务中优先级别最高的任务。
4.删除信号量
(1)OSSemDel()
原型:
OS_EVENT *OSSemDel(
OS_EVENT *pevent, //信号量的指针
INT8U opt, //删除条件选择
INT8U *err //错误信息
);
opt:指明信号量的删除条件,该参数有两个参数值可以选择:
OS_DEL_NO_PEND,当等待任务表中已没有等待任务时才删除信号量
OS_DEL_ALLWAYS,等待任务中无论是否有等待任务,都立即删除信号量。
(2)注意:只能在任务中删除信号量,不能在中断服务程序中删除。
5.查询信号量的状态
(1)OSSemQuery(),随时查询信号量的当前状态;
(2)原型:
INT8U OSSemQuery
{
OS_EVENT_ *pevent, //信号量指针
OS_SEM_DATA *pdata //存储信号量装入结构
};