ucos II 任务间 通信之三:信号量
2015-10-14 22:46
477 查看
信号量是什么?信号量有什么用?
信号量一是可以用来表示一个或多个事件的发生,二是用来对共享资源的访问。
ucos II提供了5个对信号量进行操作的函数。它们是:
1. 建立一个信号量,
OSSemCreate()
2. 等待一个信号量,
OSSemPend()
3. 发送一个信号量,
OSSemPost()
4. 无等待地请求一个信号量,
OSSemAccept()
5. 查询一个信号量的当前状态,
OSSemQuery()
OSSemCreate()的实现代码如下:
在mcu21看来,创建一个信号量,简单来说,就是申请一个事件控制块,接着初始化这个事件控制块。
首先,它从空闲任务控制块链表中得到一个事件控制块[
(1)],并对空闲事件控制链表的指针进行适当的调整,使它指向下一个空闲的事件控制块[ (2)]。如果这时有 事件 控制块可用[
(3)],就将该 事件 控制块的事件类型设置成信号量OS_EVENT_TYPE_SEM[
(4)]。其它的信号量操作函数OSSem???()通过检查该域来保证所操作的 事件控制块类型的正确。例如,这可以防止调用OSSemPost()函数对一个用作邮箱的
事件 控制块进行操作。
接着,用信号量的初始值对 事件 控制块进行初始化[(5)](如果信号量是用来表示一个或者多个事件的发生,那么该信号量的初始值应设为0,
如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1.),并调用OSEventWaitListInit()函数对事件控制任务控制块的等待任务列表进行初始化
[(6)]。因为信号量正在被初始化,所以这时没有任何任务等待该信号量。
最后,OSSemCreate()返回给调用函数一个指向 事件 控制块的指针。以后对信号量的所有操作,如OSSemPend(),
OSSemPost(),
OSSemAccept()和OSSemQuery()都是通过该指针完成的。因此,这个指针实际上就是该信号量的句柄。如果系统中没有可用的
事件 控制块,OSSemCreate()将返回一个NULL指针。
创建好一个信号之后,可以调用OSSemQuery()查询一个信号的状态。该函数有两个参数:一个是指向信号量对应事件控制块的指针pevent。;另一个是指向用于记录信号量信息的数据结构OS_SEM_DATA。
简单来说就是把信号量对应的事件控制块的信息复制到数据结构OS_SEM_DATA。
OSSemQuery()程序代码如下:
OS_EVENT *OSSemCreate (INT16U
cnt)
;该函数返回的数据类型为指针,指针指向的数据类型为OS_EVENT(事件的数据类型为结构体)。也就是函数返回一个地址,地址里存的是新创建的结构体类型所占据的内存的首地址。
OS_EVENT
*pevent;
pevent =
OSEventFreeList;
if (OSEventFreeList != (OS_EVENT
*)0) {
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
;首先创建一个指向OS_EVENT结构体类型的指针pevent;系统初始化时会创建一个空事件控制块链表,而创建的空事件控制块的数目由常数OSEventMax来决定。OSEventFreeList就指向这个空事件控制块链表的第一个,所以上面的程序里把OSEventFreeList赋给了pevent,也就是让pevent指向第一个空事件控制块,然后又让OSEventFreeList指向了空事件控制链表中的第二个。也就是从空事件链表中摘出了第一个给事件使用。
if (pevent != (OS_EVENT *)0)
{
pevent->OSEventType
= OS_EVENT_TYPE_SEM;
pevent->OSEventCnt
=
cnt;
pevent->OSEventPtr
= (void
*)0;
#if OS_EVENT_NAME_SIZE > 1
pevent->OSEventName[0] =
'?';
pevent->OSEventName[1] = OS_ASCII_NUL;
#endif
;以上就是对新创建的空任务控制块的各个量进行初始化。
OS_EventWaitListInit(pevent); ;通过调用OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent。
return
(pevent);
;返回创建的结构体类型数据的首地址的指针
信号量一是可以用来表示一个或多个事件的发生,二是用来对共享资源的访问。
ucos II提供了5个对信号量进行操作的函数。它们是:
1. 建立一个信号量,
OSSemCreate()
2. 等待一个信号量,
OSSemPend()
3. 发送一个信号量,
OSSemPost()
4. 无等待地请求一个信号量,
OSSemAccept()
5. 查询一个信号量的当前状态,
OSSemQuery()
OSSemCreate()的实现代码如下:
OS_EVENT *OSSemCreate (INT16U cnt) |
{ |
OS_EVENT *pevent; |
|
|
OS_ENTER_CRITICAL(); |
pevent = OSEventFreeList; (1) |
if (OSEventFreeList != (OS_EVENT *)0) { (2) |
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; |
} |
OS_EXIT_CRITICAL(); |
if (pevent != (OS_EVENT *)0) { (3) |
pevent->OSEventType = OS_EVENT_TYPE_SEM; (4) |
pevent->OSEventCnt = cnt; (5) |
OSEventWaitListInit(pevent); (6) |
} |
return (pevent); (7) |
} |
首先,它从空闲任务控制块链表中得到一个事件控制块[
(1)],并对空闲事件控制链表的指针进行适当的调整,使它指向下一个空闲的事件控制块[ (2)]。如果这时有 事件 控制块可用[
(3)],就将该 事件 控制块的事件类型设置成信号量OS_EVENT_TYPE_SEM[
(4)]。其它的信号量操作函数OSSem???()通过检查该域来保证所操作的 事件控制块类型的正确。例如,这可以防止调用OSSemPost()函数对一个用作邮箱的
事件 控制块进行操作。
接着,用信号量的初始值对 事件 控制块进行初始化[(5)](如果信号量是用来表示一个或者多个事件的发生,那么该信号量的初始值应设为0,
如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1.),并调用OSEventWaitListInit()函数对事件控制任务控制块的等待任务列表进行初始化
[(6)]。因为信号量正在被初始化,所以这时没有任何任务等待该信号量。
最后,OSSemCreate()返回给调用函数一个指向 事件 控制块的指针。以后对信号量的所有操作,如OSSemPend(),
OSSemPost(),
OSSemAccept()和OSSemQuery()都是通过该指针完成的。因此,这个指针实际上就是该信号量的句柄。如果系统中没有可用的
事件 控制块,OSSemCreate()将返回一个NULL指针。
创建好一个信号之后,可以调用OSSemQuery()查询一个信号的状态。该函数有两个参数:一个是指向信号量对应事件控制块的指针pevent。;另一个是指向用于记录信号量信息的数据结构OS_SEM_DATA。
简单来说就是把信号量对应的事件控制块的信息复制到数据结构OS_SEM_DATA。
OSSemQuery()程序代码如下:
INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata) |
{ |
INT8U i; |
INT8U *psrc; |
INT8U *pdest; |
|
OS_ENTER_CRITICAL(); |
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1) |
OS_EXIT_CRITICAL(); |
return (OS_ERR_EVENT_TYPE); |
} |
pdata->OSEventGrp = pevent->OSEventGrp; (2) |
psrc = &pevent->OSEventTbl[0]; |
pdest = &pdata->OSEventTbl[0]; |
for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { |
*pdest++ = *psrc++; |
} |
pdata->OSCnt = pevent->OSEventCnt; (3) |
OS_EXIT_CRITICAL(); |
return (OS_NO_ERR); |
} |
cnt)
;该函数返回的数据类型为指针,指针指向的数据类型为OS_EVENT(事件的数据类型为结构体)。也就是函数返回一个地址,地址里存的是新创建的结构体类型所占据的内存的首地址。
OS_EVENT
*pevent;
pevent =
OSEventFreeList;
if (OSEventFreeList != (OS_EVENT
*)0) {
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
;首先创建一个指向OS_EVENT结构体类型的指针pevent;系统初始化时会创建一个空事件控制块链表,而创建的空事件控制块的数目由常数OSEventMax来决定。OSEventFreeList就指向这个空事件控制块链表的第一个,所以上面的程序里把OSEventFreeList赋给了pevent,也就是让pevent指向第一个空事件控制块,然后又让OSEventFreeList指向了空事件控制链表中的第二个。也就是从空事件链表中摘出了第一个给事件使用。
if (pevent != (OS_EVENT *)0)
{
pevent->OSEventType
= OS_EVENT_TYPE_SEM;
pevent->OSEventCnt
=
cnt;
pevent->OSEventPtr
= (void
*)0;
#if OS_EVENT_NAME_SIZE > 1
pevent->OSEventName[0] =
'?';
pevent->OSEventName[1] = OS_ASCII_NUL;
#endif
;以上就是对新创建的空任务控制块的各个量进行初始化。
OS_EventWaitListInit(pevent); ;通过调用OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent。
return
(pevent);
;返回创建的结构体类型数据的首地址的指针
相关文章推荐
- 我们在程序中经常会用到MessageBox
- 我们在程序中经常会用到MessageBox
- 栈帧结构
- 银行家算法
- 银行家算法
- U-boot
- U-boot
- 栈帧结构
- NSNumber与NSInteger转换遇到的问题
- HTML5-bootstrap summernote 编辑器
- 九度OJ 1009:二叉搜索树 (二叉树)
- 在emacs中如何快速插入系统当前时间?
- iOS:CALayer核心动画层
- 使用内联函数的一个问题
- 九度OJ 1009:二叉搜索树 (二叉树)
- [ARM学习]ARM指令集详解(超…
- [ARM学习]ARM指令集详解(超…
- cocos2d-x粒子系统
- cocos2d-x粒子系统
- 等待进程