OSAL之消息管理

转载请注明出处,尊重原创;本文基于蓝牙1.3.2版本总述:

OSAL中实现对消息管理的功能实现是在osal.c 与 osal.h 文件中,对于操作系统来说,不可缺少的就是任务之间信息的传递,消息包括:信号量,互斥量,消息邮箱、消息队列等。在OSAL中仅仅实现了消息队列的功能,系统可以发送或接收消息,并对消息进行管理。

背景知识:在OSAL.H文件中

1、定义消息管理的消息首部,所有的消息构成都有它这部分;

typedef struct{ //用于消息首部 void *next; uint16 len; uint8 dest_id;} osal_msg_hdr_t;

其中next指针将消息组织成有序的链表,len为消息的长度,dest_id是目标任务id。 2、定义管理消息队列的指针类型,从这里也可以看出管理消息队列指针类型是空指针,也说明了消息结构的类型是变化的,不是固定的。 typedef void * osal_msg_q_t; 3、定义几个消息操作的宏

获得下一个消息#define OSAL_MSG_NEXT(msg_ptr)((osal_msg_hdr_t *) (msg_ptr) – 1)->next初始化一个消息队列#define OSAL_MSG_Q_INIT(q_ptr)*(q_ptr) = NULL判断消息队列是否为空#define OSAL_MSG_Q_EMPTY(q_ptr)(*(q_ptr) == NULL)获得消息队列头指针#define OSAL_MSG_Q_HEAD(q_ptr)(*(q_ptr))获得一个消息的消息长度#define OSAL_MSG_LEN(msg_ptr)((osal_msg_hdr_t *) (msg_ptr) – 1)->len获得消息发送的目标任务#define OSAL_MSG_ID(msg_ptr)((osal_msg_hdr_t *) (msg_ptr) – 1)->dest_id

4、定义一个管理消息队列的变量用于管理消息队列 osal_msg_q_t osal_qHead;

从这个图可以看出osa_qHead是指向消息空间的,但是因为消息空间不能给出一个固定的结构模式,所以他是一个控制真的形式。

API函数1、创建消息

osal_msg_allocate() 给消息分配内存空间,该函数由发送消息的任务调用以创建一个消息 参数: len-消息的长度 1、分配内存空间(消息管理首部大小+消息的长度) hdr=(osal_msg_hdr_t*)osal_mem_alloc((short)(len+sizeof( osal_msg_hdr_t )) ); 2、填充消息首部

{hdr->next = NULL;hdr->len = len;hdr->dest_id = TASK_NO_TASK;return ( (uint8 *) (hdr + 1) );//这里返回的是消息信息空间的地址 }

创建一个消息缓冲区后,下一步是在调用函数里填充消息信息空间了。然后调用osal_msg_send()函数将一个消息发送到消息队列队末尾。

2、发送消息

osal_msg_send()函数是向消息队列发送一个消息,同时还会向目标任务的事件列表里置位消息事件。 参数: destination_task:目标任务id *msg_ptr: 指向消息空间

uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ){ return ( osal_msg_enqueue_push( destination_task, msg_ptr, FALSE ) );}//他是调用了一个入队列函数,最后参赛FALSE是指明入队列末尾。也就是说发送消息只是入队列而已3、将消息入队列

osal_msg_enqueue_push( uint8 destination_task, uint8 *msg_ptr, uint8 push )函数功能是将一则消息入消息队列,同时设置目的任务的消息事件。 参数: destination_task:目标任务id *msg_ptr: 指向消息空间 push 指定是入队头还是队尾;TRUE是对头,FALSE是队尾 主要函数代码:

OSAL_MSG_ID( msg_ptr ) = destination_task;//将目标id复制给消息头dest_id if ( push == TRUE ) {// prepend the message如果push为TRUE则将消息插入到队列头部//这样说明osal_msg_push函数是仅仅将消息插入队列头部osal_msg_push( &osal_qHead, msg_ptr ); } else {// append the message这里就是将消息插入队列尾部osal_msg_enqueue( &osal_qHead, msg_ptr ); } // Signal the task that a message is waiting置位相应任务的消息事件 osal_set_event( destination_task, SYS_EVENT_MSG );对入队列调用的API讲解

osal_msg_push( &osal_qHead, msg_ptr ); 将消息插入到队列对头,当push为TRUE时候执行。&osal_qHead是队列头指针的地址,msg_ptr是指向消息空间的指针 osal_msg_enqueue( &osal_qHead, msg_ptr ); 将消息插入到队列末尾,&osal_qHead是队列头指针的地址,msg_ptr是指向消息空间的指针。

4发送消息的另外一种方式

osal_msg_push_front方式

uint8 osal_msg_push_front( uint8 destination_task, uint8 *msg_ptr ){ return ( osal_msg_enqueue_push( destination_task, msg_ptr, TRUE ) );//最后一个参数TRUE表明插入到队列头}

它与osal_msg_send唯一不同的是它将消息插入到队列头

5以上完成了一个消息的创建,发送,入队列的过程。下面就是任务消息事件的处理了。6目标任务执行处理系统消息事件1、获取该任务的消息uint8 *osal_msg_receive( uint8 task_id )osal_msg_hdr_t *listHdr;//定义用来遍历消息队列,指向当前遍历的元素 osal_msg_hdr_t *prevHdr = NULL;//用来遍历时候使用,指向foundHdr指针前一个元素 osal_msg_hdr_t *foundHdr = NULL; //指向发现符合该任务的消息 halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); // Point to the top of the queueosal_qHead指向的是消息信息结构体,不是消息头结构体 listHdr = osal_qHead; // Look through the queue for a message that belongs to the asking task while ( listHdr != NULL ) {if ( (listHdr – 1)->dest_id == task_id ){//找到了该任务的消息if ( foundHdr == NULL ){// Save the first onefoundHdr = listHdr;}else{;}}//若没找到符合的消息,那么prevHdr向下遍历,如果找到了,foundHdr不为0,prevHdr不再往下遍历了,指向foundHdr前一个元素if ( foundHdr == NULL ){prevHdr = listHdr;}listHdr = OSAL_MSG_NEXT( listHdr ); }世上最累人的事,莫过於虚伪的过日子

OSAL之消息管理

相关文章:

你感兴趣的文章:

标签云: