浅析
μCOS
/
II v2
.
85
内核
OSFlagPend
()
和
OSFlagPost
()
函数工作原理
http:
//gliethttp.cublog.cn
//
对于
flag--"
事件组
"
的使用
,
可以用一个简单的例子做说明
:
//
比如
,
我现在用迅雷下载一部
10
集的连续剧
,
我打算
10
集全部下载完成之后
,
//
才开始正式看
,
现在
3~10
集因为种子原因
,
先早下完了
,
现在第
1
集下到了
82%,
//
第
2
集下到了
97%,
因为我的计划是
10
集全部下完才开始看
,
而第
1
集和第
2
集
//
由于网络
,
种子等等各种原因
,
迟迟不能下载完成
,
进而导致我的计划被悬停
,
不能进行
,
//
已下载的
8
集
,
也因为前
2
集没能下完
,
而白白等待
---
这就等同于
flag
事件组
,
//1~10
集
,
每一集都是一个事件
,
因为我内定
,10
个事件全部完成之后
,
才进入下一事件
--"
观看
"
//
所以及早完成自己事件的第
3~10
集
,
将主动把自己通过
flag
事件组函数
OSFlagPost()
登记到事件组上
,
//
他们不关心
,
其他友邻事件完成否
,
只专注自己的事件是否完成
,
自己的事件一旦完成
//
就登记到事件组上
,
最后
3~10
集
,
都把自己登记上去了
,
只剩下第
1
集和第
2
集
,
//
一旦某天的某个时刻
,
第
2
集下完了
,
那么第
2
集也把自己登记到事件组上
,
这样整个事件距离完成
//
还剩下一个事件
,
就是第
1
集是否下载完成
,
只要第
1
集下载完成
,
那么我内定的
"
观看
"
计划
//
开始启动
,
过了
3
分钟
,
由于网速提高
,
竟以
300k
的速度开始下载第
1
集
,1
分钟之后
,
//
第
1
集也下载完成了
,
第
1
集立即调用
OSFlagPost
事件组函数
,
将自己登记到事件组上
,
//ok,OSFlagPost()
检测到所有事件已经完成
,OSFlagPost()
将是
"
我
"
自动进入下一事件
---"
观看
"
//
还有一点就是关于
flag
事件组和
Sem,Mbox,Queue
的区别之处
,flag
事件组不使用事件控制矩阵来
//
管理被阻塞在事件上的
task
进程
,flag
事件组使用
pgrp
的双向链表来挂接起所有
task,
//
在
OSFlagPost()
中将遍历这个链表
,
查找符合当前
flag
事件的
task,
将该
task
从双向链表中摘下
//
然后放入就绪控制矩阵中
,
之所以这样
,
是因为
flag
事件组不像
Sem,Mbox,Queue
那样具有二值性
,
//
即
Sem,Mbox,Queue,
要么有
,
要么没有
,flag
事件组
,
还要进一步判断
,
有的话
,
是什么程度的有
.
//----------------------------------------------------------------------
//1.OSFlagPend()
函数
OS_FLAGS OSFlagPend
(
OS_FLAG_GRP
*
pgrp
,
OS_FLAGS flags
,
INT8U wait_type
,
INT16U timeout
,
INT8U
*
perr
)
{
OS_FLAG_NODE node
;
OS_FLAGS flags_rdy
;
INT8U result
;
INT8U pend_stat
;
BOOLEAN consume
;
#
if
OS_CRITICAL_METHOD
==
3
OS_CPU_SR cpu_sr
=
0
;
#
endif
#
if
OS_ARG_CHK_EN
>
0
if
(
perr
==
(
INT8U
*)
0
)
{
return
((
OS_FLAGS
)
0
);
}
if
(
pgrp
==
(
OS_FLAG_GRP
*)
0
)
{
*
perr
=
OS_ERR_FLAG_INVALID_PGRP
;
return
((
OS_FLAGS
)
0
);
}
#
endif
if
(
OSIntNesting
>
0
)
{
//ISR
中
,
不能使用
OSFlagPend()
*
perr
=
OS_ERR_PEND_ISR
;
return
((
OS_FLAGS
)
0
);
}
if
(
OSLockNesting
>
0
)
{
//μCOS/II v2.85
内核已经被强制锁住
*
perr
=
OS_ERR_PEND_LOCKED
;
return
((
OS_FLAGS
)
0
);
}
if
(
pgrp
->
OSFlagType
!=
OS_EVENT_TYPE_FLAG
)
{
//
确保该
event
控制块是
flag
类型
*
perr
=
OS_ERR_EVENT_TYPE
;
return
((
OS_FLAGS
)
0
);
}
result
=
(
INT8U
)(
wait_type
&
OS_FLAG_CONSUME
);
if
(
result
!=
(
INT8U
)
0
)
{
//
收到指定事件们之后
,
复位
flag
事件组
,
将相应的事件标志清
0
wait_type
&=
~(
INT8U
)
OS_FLAG_CONSUME
;
consume
=
OS_TRUE
;
}
else
{
consume
=
OS_FALSE
;
}
OS_ENTER_CRITICAL
();
switch
(
wait_type
)
{
case
OS_FLAG_WAIT_SET_ALL
:
//2007-09-09 gliethttp
//flag
事件组中所有事件都置位才唤醒
flags_rdy
=
(
OS_FLAGS
)(
pgrp
->
OSFlagFlags
&
flags
);
if
(
flags_rdy
==
flags
)
{
//flag
事件组中指定的所有事件都已经登记了
if
(
consume
==
OS_TRUE
)
{
//
清除
flag
事件组中的相应事件标志位
pgrp
->
OSFlagFlags
&=
~
flags_rdy
;
}
OSTCBCur
->
OSTCBFlagsRdy
=
flags_rdy
;
//
返回成功的
flag
事件组值
OS_EXIT_CRITICAL
();
*
perr
=
OS_ERR_NONE
浅析μCOS/II v2.85内核OSFlagPend()和OSFlagPost()
最新推荐文章于 2023-03-16 01:17:47 发布
本文深入探讨了μCOS/II v2.85操作系统中关于OSFlagPend()和OSFlagPost()两个关键函数的使用和作用。OSFlagPend()用于任务等待标志的设置,而OSFlagPost()则用于标志的发布,这两个函数在多任务环境下协调任务间通信起着至关重要的作用。通过实例分析,详细阐述了它们在任务调度和同步中的具体应用。
摘要由CSDN通过智能技术生成