Chinaunix首页 | 论坛 | 博客
  • 博客访问: 792039
  • 博文数量: 83
  • 博客积分: 7030
  • 博客等级: 少将
  • 技术积分: 1097
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-06 15:50
文章分类

全部博文(83)

文章存档

2011年(2)

2010年(9)

2009年(56)

2008年(16)

我的朋友

分类:

2009-11-01 22:00:28

为什么要用:
任务间的通信可以通过全局变量或者信号量来完成。全局变量虽然可以承载通信的内容,但是接收方无法意识到信息的到达,除非发送方向接收方发送一个信号量,或者接收方不断该全局变量;信号量可以立即使接收方知道某个事件的发生,但无法传递具体内容。用信号量进行通信就像我们只拨通别人的手机而不与之通话;用消息队列或者邮箱进行通信则可达到既 拨通别人的手机又与之通话的效果。换句话说,消息队列和邮箱可以及时传送事件的内容。
邮箱通信的机理:
发送方通过内核服务把一封邮件投递到邮箱,内核完成投递任务后通知等待列表中的接收方收取邮件。在整个投递过程中,内核充当了邮递员的角色。这里的“邮件”通常是一个指针,接收方可以通过该指针获取邮件内容。
邮箱的基本操作:
内核通常提供如下的邮箱服务:初始化邮箱的内容。邮箱最初可以包含或者不包含邮件。把邮件发送到邮箱(post)。如果邮箱已满,则返回错误信息(OS_MBOX_FULL)。以“挂起”方式接收邮件(pend)。如果邮箱为空,则把取信者挂起;若超过一定时间邮箱仍为空,则返回超时信息。
以“非挂起”方式接收邮件(accept)。如果邮箱为空,则返回一个空指针。
当希望一次性向某个任务发送多则消息时,邮箱就有点见肘了。因为一个邮箱只能装一封信。把多上邮箱集中到一起管理和使用就变成了消息队列,所以消息队列的操作和邮箱很相似。可以简单地认为,消息队列是邮箱数组。
如果发送者是一对一的方式发送邮件,则等待列表中的优先级最高的任务将获取邮件;如果是以广播的方式发送邮件,则等待该邮件的所有任务将获得此邮件。

/********************************************************************
* 文 件 名:main.c
* 功    能:利用消息队列和邮箱,实现任务间的通讯。
* 说    明:观察信息窗口中由jtag_uart输出的信息。
********************************************************************/
#include
#include
#include "includes.h"   /* MicroC/OS-II总头文件 */
#include "alt_ucosii_simple_error_check.h" /* 错误处理软件模块 */

#define   WAIT_FOREVER         0     /* 超时常数,0表示永远等待 */
#define   TASK_STACKSIZE       2048 /* 定义任务栈大小          */
/* 定义各任务任务栈 */
OS_STK    initialize_task_stk[TASK_STACKSIZE];
OS_STK    msg_sender_stk[TASK_STACKSIZE];
OS_STK    msg_receiver1_stk[TASK_STACKSIZE];
OS_STK    msg_receiver2_stk[TASK_STACKSIZE];
OS_STK    mail_send1_stk[TASK_STACKSIZE];
OS_STK    mail_send2_stk[TASK_STACKSIZE];
OS_STK    mail_send3_stk[TASK_STACKSIZE];
OS_STK    print_task_stk[TASK_STACKSIZE];

/* 分配各任务优先级 */
#define INITIALIZE_TASK_PRIORITY 6
#define PRINT_TASK_PRIORITY    7
#define MSG_SENDER_PRIORITY    8
#define MSG_RECEIVER1_PRIORITY   9
#define MSG_RECEIVER2_PRIORITY   10
#define MAIL_SEND1_PRIORITY    11
#define MAIL_SEND2_PRIORITY    12
#define MAIL_SEND3_PRIORITY    13

/* 定义消息队列 */
#define   MSG_QUEUE_SIZE 30                /* 消息队列大小     */
OS_EVENT *msgqueue;                         /* 消息队列事件指针 */
void       *msgqueueTbl[MSG_QUEUE_SIZE]; /* 队列缓冲区       */

/* 定义三个邮箱 */
OS_EVENT *mailbox1;
OS_EVENT *mailbox2;
OS_EVENT *mailbox3;

/* 定义任务状态记录 */
INT32U number_of_messages_sent = 0;              /* 发出消息的数量           */
INT32U number_of_messages_received_task1 = 0; /* 接收任务1收到消息的数量 */
INT32U number_of_messages_received_task2 = 0; /* 接收任务2收到消息的数量 */

/* 局部函数声明 */
int initOSDataStructs(void); /* 初始化消息队列和邮箱的数据结构 */
int initCreateTasks(void);    /* 初始化任务                     */

/* 每5秒打印一次使用消息队列的进行通讯的任务状态信息. */
void PrintTask(void* pdata)
{
while (1)
{
    OSTimeDlyHMSM(0, 0, 5, 0);
    printf("************************************************************\n");
    printf("The number of messages sent by the MsgSender:         %lu\n",
            number_of_messages_sent);
    printf("\n");
    printf("The number of messages received by the MsgReceiver1: %lu\n",
            number_of_messages_received_task1);
    printf("\n");
    printf("The number of messages received by the MsgReceiver2: %lu\n",
            number_of_messages_received_task2);
    printf("************************************************************\n");
    printf("\n");
}
}
/* 消息发送任务: 将消息通过消息队列广播给所有等待消息的任务,当队列满时,延时1s */
void MsgSender(void* pdata)
{
INT8U return_code = OS_NO_ERR; /* 系统调用的返回状态 */
INT32U msg = 0;                   /* 欲发出的消息        */
OS_Q_DATA queue_data; /* 用于保存从消息队列的事件控制块中获取的数据信息 */

while (1)
{
    return_code = OSQQuery(msgqueue, &queue_data); /* 查询本消息队列的信息    */
    alt_ucosii_check_return_code(return_code);       /* 检查系统调用的返回状态 */
    if(queue_data.OSNMsgs < MSG_QUEUE_SIZE)           /* 查询消息队列是否已满    */
    { /* 消息队列未满,将消息(msg)通过消息队列(msgqueue)广播给所有等待消息的任务*/
      return_code = OSQPostOpt(msgqueue, (void *)&msg, OS_POST_OPT_BROADCAST);
      alt_ucosii_check_return_code(return_code);      /* 检查系统调用的返回状态 */
      msg++;                           /* 产生新消息          */
      number_of_messages_sent++;   /* 记录发出消息的条数 */
    }
    else
    { /* 消息队列已满,延时1s */
      OSTimeDlyHMSM(0, 0, 1, 0);
    }
}
}

/* 消息接收任务1: 每300ms接收一次消息队列的消息*/
void MsgReceiver1(void* pdata)
{
INT8U return_code = OS_NO_ERR; /* 系统调用的返回状态 */
INT32U *msg;                        /* 存储接收到的消息   */

while (1)
{ /* 到msgqueue接收消息,如果消息队列为空,则一直等待 */
    msg = (INT32U *)OSQPend(msgqueue, WAIT_FOREVER, &return_code);
    alt_ucosii_check_return_code(return_code);
    number_of_messages_received_task1++;   /* 接到消息,计数器加1 */
    OSTimeDlyHMSM(0, 0, 0, 300);             /* 延时300ms          */
}
}
/* 消息接收任务1: 每1s接收一次消息队列的消息*/
void MsgReceiver2(void* pdata)
{
INT8U return_code = OS_NO_ERR; /* 系统调用的返回状态 */
INT32U *msg;                        /* 存储接收到的消息   */

while (1)
{ /* 到msgqueue接收消息,如果消息队列为空,则一直等待 */
    msg = (INT32U *)OSQPend(msgqueue, WAIT_FOREVER, &return_code);
    alt_ucosii_check_return_code(return_code);
    number_of_messages_received_task2++;     /* 接到消息,计数器加1 */
    OSTimeDlyHMSM(0, 0, 1, 0);                 /* 延时1s              */
}
}

/* 邮件发送任务1: 从mailbox1中收取信息,把信息加1后发到mailbox2*/
void MailSend1(void* pdata)
{
INT8U return_code = OS_NO_ERR; /* 系统调用的返回状态 */
INT32U *mbox1_contents;           /* 指向邮件内容的指针 */

while (1)
{ /* 从mailbox1接收邮件,如果邮箱为空,则一直等待 */
    mbox1_contents = (INT32U *)OSMboxPend(mailbox1, WAIT_FOREVER, &return_code);
    alt_ucosii_check_return_code(return_code);
   
    /* 输出邮件内容,并把内容加1 */
printf("Task1 received the message: %lu in mailbox 1\n",
(*mbox1_contents)++);
    printf("Task1 incremented the message and placed it into mailbox 2\n");
    printf("\n");
    return_code = OSMboxPost(mailbox2,
                            (void *)mbox1_contents); /* 把邮件发送到mailbox2 */
    alt_ucosii_check_return_code(return_code);
   }
}
/* 邮件发送任务2: 从mailbox2中收取信息,把信息加1后发到mailbox3*/
void MailSend2(void* pdata)
{
INT8U return_code = OS_NO_ERR;   /* 系统调用的返回状态 */
INT32U *mbox2_contents;           /* 指向邮件内容的指针 */

while(1)
{ /* 从mailbox1接收邮件,如果邮箱为空,则一直等待 */
    mbox2_contents = (INT32U *)OSMboxPend(mailbox2, WAIT_FOREVER, &return_code);
    alt_ucosii_check_return_code(return_code);
    /* 输出邮件内容,并把内容加1 */
    printf("Task2 received the message: %lu in mailbox 2\n", (*mbox2_contents)++);
    printf("Task2 incremented the message and placed it into mailbox 3\n");
    printf("\n");
    /* 把邮件发送到mailbox3 */
    return_code = OSMboxPost(mailbox3,(void *)mbox2_contents);
    alt_ucosii_check_return_code(return_code);
}
}

/* 邮件发送任务3: 从mailbox3中收取信息,把信息加1后发到mailbox1*/
void MailSend3(void* pdata)
{
INT8U return_code = OS_NO_ERR;
INT32U *mbox3_contents;

while (1)
{
    mbox3_contents = (INT32U *)OSMboxPend(mailbox3, WAIT_FOREVER, &return_code);
    alt_ucosii_check_return_code(return_code);
   
    printf("Task3 received the message: %lu in mailbox 3\n", (*mbox3_contents)++);
    printf("Task3 incremented the message and placed it into mailbox 1\n");
    printf("\n");
   
    usleep(3000000); /* 延时3000000us */
    /* 把邮件发送到mailbox1 */
    return_code = OSMboxPost(mailbox1,(void *)mbox3_contents);
    alt_ucosii_check_return_code(return_code);
}
}
/* 初始化各子任务 */
void initialize_task(void* pdata)
{
INT8U return_code = OS_NO_ERR;
INT32U mbox1_contents = 0;
/* 初始化消息队列和邮箱的数据结构 */
initOSDataStructs();

/* 创建个子任务 */
initCreateTasks();

/* 向mailbox1发送一封邮件*/
return_code = OSMboxPost(mailbox1, (void *)&mbox1_contents);
alt_ucosii_check_return_code(return_code);

return_code = OSTaskDel(OS_PRIO_SELF);
alt_ucosii_check_return_code(return_code);
while (1);
}

int main (int argc, char* argv[], char* envp[])
{
INT8U return_code = OS_NO_ERR;
/* 创建父任务 */
return_code = OSTaskCreateExt(initialize_task,
                             NULL,
                             &initialize_task_stk[TASK_STACKSIZE],
                             INITIALIZE_TASK_PRIORITY,
                             INITIALIZE_TASK_PRIORITY,
                             initialize_task_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
OSStart(); /* 启动OS */
return 0;
}
/* This function simply creates the three Mailboxes */

int initOSDataStructs(void)
{ /* 初始化邮箱的数据结构 */
mailbox1 = OSMboxCreate((void *)NULL);
mailbox2 = OSMboxCreate((void *)NULL);
mailbox3 = OSMboxCreate((void *)NULL);
/* 初始化消息队列的数据结构 */
msgqueue = OSQCreate(&msgqueueTbl[0], MSG_QUEUE_SIZE);
return 0;
}

int initCreateTasks(void)
{
INT8U return_code = OS_NO_ERR;
/* 创建打印任务 */
return_code = OSTaskCreateExt(PrintTask,
                             NULL,
                             &print_task_stk[TASK_STACKSIZE],
                             PRINT_TASK_PRIORITY,
                             PRINT_TASK_PRIORITY,
                             print_task_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MsgSender任务 */
return_code = OSTaskCreateExt(MsgSender,
                             NULL,
                             &msg_sender_stk[TASK_STACKSIZE],
                             MSG_SENDER_PRIORITY,
                             MSG_SENDER_PRIORITY,
                             msg_sender_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MsgReceiver1任务 */
return_code = OSTaskCreateExt(MsgReceiver1,
                             NULL,
                             &msg_receiver1_stk[TASK_STACKSIZE],
                             MSG_RECEIVER1_PRIORITY,
                             MSG_RECEIVER1_PRIORITY,
                             msg_receiver1_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MsgReceiver2任务 */
return_code = OSTaskCreateExt(MsgReceiver2,
                             NULL,
                             &msg_receiver2_stk[TASK_STACKSIZE],
                             MSG_RECEIVER2_PRIORITY,
                             MSG_RECEIVER2_PRIORITY,
                             msg_receiver2_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MailSend1任务 */
return_code = OSTaskCreateExt(MailSend1,
                             NULL,
                             &mail_send1_stk[TASK_STACKSIZE],
                             MAIL_SEND1_PRIORITY,
                             MAIL_SEND1_PRIORITY,
                             mail_send1_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MailSend2任务 */
return_code = OSTaskCreateExt(MailSend2,
                             NULL,
                             &mail_send2_stk[TASK_STACKSIZE],
                             MAIL_SEND2_PRIORITY,
                             MAIL_SEND2_PRIORITY,
                             mail_send2_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
/* 创建MailSend3任务 */
return_code = OSTaskCreateExt(MailSend3,
                             NULL,
                             &mail_send3_stk[TASK_STACKSIZE],
                             MAIL_SEND3_PRIORITY,
                             MAIL_SEND3_PRIORITY,
                             mail_send3_stk,
                             TASK_STACKSIZE,
                             NULL,
                             0);
alt_ucosii_check_return_code(return_code);
return 0;
}
/* This is the end of this file */

阅读(1619) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~