Sie sind auf Seite 1von 10

Ex.No.

8
INTER-TASK COMMUNICATION USING MESSAGE QUEUE
Date:

AIM

To create multiple tasks and make them to share the information between them using
message queue.

APPARATUS REQUIRED

 DOSBOX,
 Micrium ii operating system..

DESCRIPTION

A message queue is used to send one or more messages to a task. A message queue
is basically an array of mailboxes. Through a service provided by the kernel, a task or an ISR
can deposit a message (the pointer) into a message queue. Similarly, one or more tasks can
receive messages through a service provided by the kernel. Both the sending task and
receiving task or tasks have to agree as to what the pointer is actually pointing to. Generally,
the first message inserted in the queue will be the first message extracted from the queue
(FIFO). In addition, to extract messages in a FIFO fashion, µC/OS-II allows a task to get
messages Last-In-First-Out (LIFO). “Queue” is one of the Inter-task communication method
which is used as a shared memory location used to send one or more messages to a task. It
is an array of mailboxes. Through a service provided by the kernel, a task or an ISR can
deposit a message into a message queue. One or more tasks can receive messages through
a service provided by the kernel. Both the sender and receiving task have to agree as to what
the pointer is actually pointing to. The first message inserted in the queue is the first message
extracted from the queue (FIFO). In addition, to extract messages in a FIFO, it allows a task
to get messages Last-In-First-Out (LIFO). A waiting list is associated with each message
queue, in case more than one task is to receive messages through the queue. The kernel
allows the task waiting for a message to specify a timeout. If a message is not received before
the timeout expires, the requesting task is made ready to run, and an error code (indicating a
timeout has occurred) is returned to it. A task desiring a message from an empty queue is
suspended and placed on the waiting list until a message is received. When a message is
deposited into the queue, either the highest priority task, or the first task to wait for the
message is given the message.
Fig.8.1. task depositing message into message queue

Fig.8.1. shows depositing a message into a queue. The “10” indicates the number of
messages that can accumulate in the queue. A “0” next to the hourglass indicates that the
task will wait forever for a message to arrive.

MESSAGE QUEUE MANAGEMENT APIs


 OSQCreate()
A message queue needs to be created before it can be used. Creating a queue is
done by calling OSQCreate() and passing it two arguments: a pointer to an array that
will hold the messages and the size of this array. The message queue is assumed to
be initially empty – it doesn’t contain any messages.
Syntax
OSQCreate (void **start, INT16U size)
 OSQDel()
This function is used to delete a message queue. Before deleting a message queue,
the task which is accessing it has to be deleted in order to avoid that multiple tasks
could make attempt to access a deleted message queue. Before you would delete a
message queue, you would first delete all the tasks that access the message queue.
Syntax
OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
 OSQPend()
This function is used to wait for a message to arrive at the queue. If the queue was
empty, the calling task needs to be put to sleep until another task sends a message
through the mailbox. OSQPend() allows to specify a timeout value as one of its
arguments. It is used to avoid waiting indefinitely for a message to arrive at the queue.
If the timeout value is nonzero, OSQPend() suspends the task until the mailbox
receives a message or the specified timeout period expires. Note that a timeout value
of 0 indicates that the task is willing to wait forever for a message to arrive. To put the
calling task to sleep, OSQPend() sets the status flag in the task’s TCB to indicate that
the task is suspended waiting for a queue.
Syntax
OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
 OSQPost()/OSQPostFront()
This function is used to deposit a message in a queue in FIFO. It is done by calling
OSQPost(). OSQPost() then checks to see if any task is waiting for a message to arrive
at the queue. If the highest priority task is waiting for the message it is removed from
the waiting list and the task is made to ready to run. If there are no tasks waiting the
message to post needs to be placed in the queue. OSQPost() adjust the circular buffer
pointer to prepare for the next post. OSQPostFront() is identical to OSQPost() which
deposits the message in LIFO.

 OSQAccept()
This function is used to obtain a message from the queue without putting a task to
sleep if the queue is empty. It is done by calling the OSQAccept(). If a message is
available, the oldest message (FIFO order) is retrieved from the queue and copied to
the local pointer msg and the number of entries in the queue is decreased by one to
reflect the extraction. OSQAccept() then adjust the circular queue pointer by moving
the pointer to the next entry. If there were no entries in the queue, the local pointer is
set to NULL.
Syntax
OSQAccept (OS_EVENT *pevent)
 OSQQuery()
It is used to obtain the status of the message queue. It takes a “snapshot” of an task
control block that is used as a queue. It needs to allocate a variable of
type OS_Q_DATA that will be used to receive the information about desired queue.
Syntax
OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
 OSQFlush()
OSQFlush() allows you to remove all the messages posted to a queue and basically
start with a fresh queue.
Syntax
OSQFlush (OS_EVENT *pevent)
PROGRAM

#include "includes.h"
#include "OS_CFG.H"
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/

#define TASK_STK_SIZE 2048 /* Size of each task's stacks (# of WORDs) */

/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
OS_STK Task1Stk[TASK_STK_SIZE]; /* Task #1 task stack */
OS_STK Task2Stk[TASK_STK_SIZE];
OS_STK Task3Stk[TASK_STK_SIZE];
OS_STK Task4Stk[TASK_STK_SIZE];
OS_STK Task5Stk[TASK_STK_SIZE];
OS_STK Task6Stk[TASK_STK_SIZE];
OS_STK Task7Stk[TASK_STK_SIZE];
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void Task1(void *data);
void Task2(void *data);
void Task3(void *data);
void Task4(void *data);
void Task5(void *data);
void Task6(void *data);
void Task7(void *data);
/*$PAGE*/
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
OS_EVENT *msg;
OS_Q_DATA *p;
void *a[5];
int choice;
int count;
void main (void)
{
OSInit(); /* Initialize uC/OS-II */
PC_VectSet(uCOS,OSCtxSw);
msg=OSQCreate(a[5],5);
OSTaskCreate(Task1,(void *)1,&Task1Stk[TASK_STK_SIZE - 1],1);
OSTaskCreate(Task2,(void *)2,&Task2Stk[TASK_STK_SIZE - 1],2);
OSTaskCreate(Task3,(void *)3,&Task3Stk[TASK_STK_SIZE - 1],3);
OSTaskCreate(Task4,(void *)4,&Task4Stk[TASK_STK_SIZE - 1],4);
OSTaskCreate(Task5,(void *)5,&Task5Stk[TASK_STK_SIZE - 1],5);
OSTaskCreate(Task6,(void *)6,&Task6Stk[TASK_STK_SIZE - 1],6);

OSStart(); /* Start multitasking */


}
/*
*********************************************************************************************************
* TASK #1
*********************************************************************************************************
*/
void Task1 (void *pdata)
{

INT8U err;
pdata=pdata;
OSTaskSuspend(2);
OSTaskSuspend(3);
printf("\n\t\t***Task 1***");
for(;;)
{
printf("\nchoose option for \n1.FIFO\n2.LIFO");
printf("\nchoice = ");
scanf("%d",&choice);
if(choice==1)

OSTaskResume(2);
else if(choice==2)
OSTaskResume(3);

printf("\n\t\tSuspending TASK1");
OSTaskSuspend(OS_PRIO_SELF);
}
}
/*
*********************************************************************************************************
* TASK #2
*********************************************************************************************************
*/
void Task2 (void *pdata)
{
INT8U err;

int i;
char **n;
int a;
pdata=pdata;
printf("\n\t\t***Task 2***");

printf("\nenter the number of students:");


scanf("%d",&a);
count=a;
n = malloc(sizeof(char*) * a);

printf("\nenter the names of the students\n");

for(i=0;i<a;i++)
{
n[i] = malloc(sizeof(char) * 50);
scanf("%s",n[i]);
OSQPost(msg,n[i]);
}

printf("\n\t\tSuspending TASK2");
OSTaskSuspend(OS_PRIO_SELF);

/*
*********************************************************************************************************
* TASK #3
*********************************************************************************************************
*/
void Task3 (void *pdata)
{
INT8U err;

int i;
int a;
char **n;
pdata=pdata;
printf("\n\t\t***Task 3***");

printf("\nenter the number of students:");


scanf("%d",&a);
count=a;

n = malloc(sizeof(char*) * a);

printf("enter the names of the students\n");

for(i=0;i<a;i++)
{
n[i] = malloc(sizeof(char) * 50);
scanf("%s",n[i]);
OSQPostFront(msg,n[i]);
}

printf("\n\t\tSuspending TASK3");
OSTaskSuspend(OS_PRIO_SELF);

/*
*********************************************************************************************************
* TASK #4
*********************************************************************************************************
*/
void Task4 (void *pdata)
{
INT8U *err;

char *str;
int j;
pdata=pdata;
printf("\n\t\t***Task 4***");
OSQQuery(msg,p);
printf("\nQueue details after flushing.....\nSize:%d\nNo. of entries:%d\n",p->OSQSize,p-
>OSNMsgs);

printf("\nMessages received from queue are");


for(j=0;j<count;j++)
{
str=OSQPend(msg,0,err);
printf("\n %s",str);

printf("\n\t\tSuspending TASK4");
OSTaskSuspend(OS_PRIO_SELF);

}
/*
*********************************************************************************************************
* TASK #5
*********************************************************************************************************
*/
void Task5 (void *pdata)
{
INT8U err;
pdata=pdata;
printf("\n\t\t***Task 5***");
for (;;)
{

printf("\n..................Flushing queue..................");
OSQFlush(msg);
OSQQuery(msg,p);
printf("\nQueue details after flushing.....\nSize:%d\nNo. of entries:%d\n",p->OSQSize,p-
>OSNMsgs);
printf("\nStart entering data a new data");
OSTaskResume(1);

OSTaskResume(4);
printf("\n\t\tSuspending TASK5");
OSTaskSuspend(OS_PRIO_SELF);
}
}

/*
*********************************************************************************************************
* TASK #6
*********************************************************************************************************
*/
void Task6 (void *pdata)
{
INT8U *err;
pdata=pdata;
printf("\n\t\t***Task 6***");
for (;;)
{
OSQDel(msg,OS_DEL_NO_PEND,err);
if(*err==OS_NO_ERR)
{
printf("\nMessage Queue DELETED");
}
printf("\n\t\tSuspending TASK6");
OSTaskSuspend(OS_PRIO_SELF);
}
}
OBSERVATIONS

Input data

FIFO ORDER

LIFO ORDER

Fig.8.2. execution of the code for message queue

Fig.8.2. shows message queue of size 5 is created before the start of execution of
tasks. Task 1 asks for the manner in which message needs to be extracted from the message
queue i.e.,FIFO(First-In-First-Out) or LIFO(Last-In-First-Out). Depending on the choice ,task
2 or task 3 is executed. Task 2 for posting of message in FIFO fashion and task 3 for posting
of message in LIFO fashion. Task 4 extracts the message from queue based on which
order(FIFO or LIFO) they were posted and prints them. OSQQuery() is used to get the details
about the queue like the size of queue and number of entries in queue. On execution of task
5, the queue is flushed i.e. all the entries in the queue are deleted by the OSQFlush()
command. Previously FIFO order was used to enter data, after flushing of queue the data is
posted in LIFO fashion as shown in Fig.8.2. Task 6 then deletes the queue after checking that
the queue to be deleted is empty.

RESULT

Thus, the inter-task communication between the multiple tasks using message queue
is done by using various Message queue APIs with Micrium ii OS and the desired outcome is
achieved.

Das könnte Ihnen auch gefallen