作者:jk.li (jk.li@foxmail.com)
引入事件标志组的目的是为了,在一个任务和多个任务之间进行同步,例如有一做饭任务,需要打水任务和买米任务的支持,只有打水任务和买米任务都完成后,做饭任务在开始执行。
等待类型一共有4中分别是:
OS_FLAG_WAIT_SET_ALL
OS_FLAG_WAIT_SET_ANY
OS_FLAG_WAIT_CLR_ALL
OS_FLAG_WAIT_CLR_ANY
WAIT_SET_ALL:意味着所有的条件都要被置位才能继续执行,好比你要做饭,必须有水和米缺一不可。
WAIT_SET_ANY:任何一个条件被置位都能继续执行,去饭馆吃饭,点了2个菜,那个菜上来了就可以开动了。
WAIT_CLR_ALL:所有的条件都被清除了才能继续执行,好比想结束游戏,必须清除所有的敌人。
WAIT_CLR_ANY:任何一个条件被被清除了都能继续执行,在游戏过程中,清除任何一个人质,游戏也结束了。
其实只要有两种等待类型就够用了
一个使用event flag的例子:
#define 水 0x01
#define 米 0x02
#define 青菜 0x04
#define 肉 0x08
static void Task_做饭(void *pdata)
{
While (1) {
OSFlagPend( eflag, 水 | 米, OS_FLAG_WAIT_SET_ALL, 0, &err); //等待水、米全部到齐后开始做饭
}
}
static void Task_做菜(void *pdata)
{
While (1) {
OSFlagPend( eflag, 青菜 | 肉, OS_FLAG_WAIT_SET_ANY, 0, &err); //青菜或者肉有一样到位了就可以开始做菜啦
}
}
static void Task_打水(void *pdata)
{
While (1) {
OSFlagPost(eflag, 水, OS_FLAG_SET, &err);
}
}
static void Task_买米(void *pdata)
{
While (1) {
OSFlagPost(eflag, 米, OS_FLAG_SET, &err);
}
}
static void Task_买菜(void *pdata)
{
While (1) {
OSFlagPost(eflag, 青菜, OS_FLAG_SET, &err);
}
}
static void Task_买肉(void *pdata)
{
While (1) {
OSFlagPost(eflag, 肉, OS_FLAG_SET, &err);
}
}
某一时刻事件标志组状态图
有了前面的基础理解OSFlagPend就非常的简单,他做了如下工作:
1、按规则比较参数中的flag与事件标志组的flag,这里的规则就是前面提到的,全部满足还是任意一个满足
2、如果满足条件,则获得该事件标志组返回
3、如果不满足,则将该等待插入事件标志组等待列表
OSFlagPost则做了如下工作:
1、设置事件标志组的flag
2、轮询等待列表,看那个满足要求,如果满足的所有的条件,则移除该节点,并将该任务放入就绪队列,这样下次调度的时候,该任务就有机会运行了