您的位置:首页 > 其它

实时操作系统μC/OS-Ⅱ读书笔记(4)

2016-09-15 21:34 246 查看
第4章 任务的同步与通信

4.1 任务的同步和事件

☆任务间的制约关系:

直接制约:源于任务之间的合作。

间接制约:源于对资源的共享。

因此,多任务合作过程中,操作系统要解决两个问题:

1. 各任务间应该有一种互斥关系

2. 相关的任务在执行上要有先后次序

☆事件:μC/OS-Ⅱ实现任务之间通信所使用的中间环节,例如:信号量、邮箱(消息邮箱)和消息队列。

☆μC/OS-Ⅱ把任务发送事件、请求事件以及其他对事件的操作都定义为全局变量,以供应用程序的所有任务来调用。

☆信号量

是一类事件

最初目的:为了给共享资源设立一个标志,该标志表示该共享资源被占用情况

互斥型信号量:是一个二值信号量,可以实现共享资源的独占式占用。

某一任务发现信号量为“1”时,可以进行共享资源的访问,同时需要把信号量变为“0”,该任务使用完共享资源后,需要把信号量由“0”变为“1”。

☆为了解决任务始终等不到信号量而不能运行出现的死机的现象,可以给等待信号量的任务设置一个等待时限,当等待信号量的任务因等待某信号量的时间超过该时限,可以使等待任务脱离等待状态而继续运行。

☆消息邮箱:

在多任务操作系统中,任务间传递消息缓冲区来传递数据,用来传递消息缓冲区指针的数据结构,就是消息邮箱。

☆消息队列:

可以传递多个消息的数据结构,传递的是一个指针数组,数组的每一个元素都存放一个消息缓冲区指针。

4.2 事件控制块及事件处理函数

☆等待任务列表:一个INT8U类型的数组OSEventTbl[]作为等待事件任务的记录表。

☆等待任务两方面的管理:

1.对等待事件所有任务记录并排序

2.允许等待任务有一个等待时限,即当等待任务认为等不及时可以退出对事件的请求,防止死锁。

☆等待任务表以任务的优先级别为顺序为每个任务分配一个二进制单位,该位的“1”表示这一位对应的任务为事件的等待任务,“0”不是等待任务。

☆OSEventGrp:一个INT8U类型的变量,表示等待任务表中的任务组,可以加快对等待任务表的访问速度。

☆等待任务的等待时限:记录在等待任务的任务控制块TCB的成员OSTCBDly中,并在每个时钟节拍中断服务程序中对该数据进行维护。每当有任务的等待时限到时,将该任务从等待任务表中删除,并使其进入就绪状态。

☆事件控制块的结构(ECB)

描述诸如信号量、邮箱(消息邮箱)和消息队列等事件的数据结构。

定义在文件μC/OS-Ⅱ.H中

结构:

typedef struct

{

INT8U OSEventType; //事件的类型

INT16U OSEventCnt; //信号量计数器

void * OSEventPtr; //消息或消息队列的指针

INT8U OSEventGrp; //等待事件的任务组

INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; //任务等待表

};OS_EVENT;

☆OSEventType可取的值

OSEventType的值 说明

OS_Event_TYPE_SEM 表明事件是信号量

OS_EVENT_TYPE_MUTEX 表明事件是互斥型信号量

OS_EVENT_TYPE_MBOX 表明事件是消息邮箱

OS_EVENT_TYPE_Q 表明事件是消息队列

OS_EVENT_TYPE_UNUSED 空事件控制块

☆操作事件控制块的函数

供操信号量、消息邮箱和消息队列等事件的函数调用

1. OS_EventWaitListInit():事件控制块的初始化函数

原型:

void OS_EventWaitListInit(

OS_EVENT *pevent

//事件控制块的指针

);

作用:把变量OSEventGrp及任务等待表中的每一位都清0,即令事件的任务表中不含有任何等待任务。

在任务调用函数OSXXXCreate()创建事件时被函数OSXXXCreate()所调用。

XXX的含义

XXX 含义

Sem 对信号量进行操作的函数

Mutex 对互斥型信号量进行操作的函数

Mbox 对消息邮箱进行操作的函数

Q 对消息队列进行操作的函数

2. OS_EventTaskWait():使一个任务进入等待状态的函数

原型:

void OS_EventTaskWait(

OS_EVENT *pevent

//事件控制块的指针

);

在任务调用函数OSXXXPend()请求一个事件时被函数OSXXXPend所调用。

3. OS_EventTaskRdy():使一个正在等待的任务进入就绪状态的函数

原型:

INT8U OS_EventTaskRdy(

OS_EVENT *pevent,

//事件控制块的指针

void * msg,

//未使用

INT8U msk

//清除TCB状态标识掩码

);

在任务调用函数OSXXXPost()发送一个事件时被函数OSXXXPost()所调用。

4. OS_EventTO():使一个等待超时的任务进入就绪状态的函数

原型:

void OS_EventTO(

OS_EVENT *pevent

//事件控制块的指针

);

在任务调用OSXXXPend()请求一个事件时被函数OSXXXPend()所调用。

☆空事件控制块链表

形成:在μC/OS-Ⅱ初始化时,系统会在初始化函数OSInit()中按应用程序使用事件的总数OS_MAX_EVENTS(在文件OS_CEG.H中定义),创建OS_MAX_EVENTS个空事件控制块并借用成员OSEventPtr作为链接指针,把这些空事件控制块链接成一个单向链表,链表中的所有控制块尚未与具体事件相关联。

每当应用程序创建一个事件时,系统就会从链表中取出一个空事件控制块,并对它进行初始化以描述该事件。应用程序删除一个事件时,会将该事件的控制块归还给空事件控制块链表。

4.3 信号量及其操作

☆信号量:信号量计数器和等待任务表组成

每当有任务申请信号量时,如果信号量计数器OSEventCnt的值大于0,则把该值减1并使任务继续运行,如果OSEventCnt的值为0,则会将任务列入任务等待表OSEventTbl[],使任务处于等待状态。

如果有正在使用信号量的任务释放了该信号量,则会在任务等待表中找出优先级别最高的等待任务,并在使它就绪后调用调度器引发一次调度;如果任务等待表中已经没有等待任务,则信号量计数器就加1。

信号量不使用事件控制块的成员OSEventPtr。

☆信号量的操作:

1.创建信号量:

调用函数OSSemCreate()创建信号量:

原型:

OS_EVENT *OSSemCreate(

INT16U cnt

//信号量计数器初值

);

返回值为已创建的信号量的指针

2.请求信号量:

函数OSSemPend()

原型:

void OSSemPend(

OS_EVENT *pevent,

//信号量的指针

INT16U timeout,

//等待时限

INT8U *err

//错误信息

);

timeout如果为0,则表明任务的等待时间为无限长

若函数调用成功,err的值为OS_NO_ERR;

失败,err的值根据具体错误,为OS_ERR_PEND_ISR、

3. 发送信号量

4. 删除信号量

5. 查询信号量的状态
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息