實現基於VxWorks的消息隊列通信機制的C/S通信

寫在前面


要實現如圖所示的C/S通信需要掌握的知識有:

1.VxWorks的消息隊列的API(具體內容可以在VxWorks內核源碼的目錄下的src/wv/msgQlib.c這個文件中找到)

主要用到的方法有:msgQCreate,msgQSend,msgQReceive

MSG_Q_ID msgQCreate
    (
    int         maxMsgs,        /* max messages that can be queued */
    int         maxMsgLength,   /* max bytes in a message */
    int         options         /* message queue options */
    )

STATUS msgQSend
    (
    FAST MSG_Q_ID       msgQId,         /* message queue on which to send */
    char *              buffer,         /* message to send */
    FAST UINT           nBytes,         /* length of message */
    int                 timeout,        /* ticks to wait */
    int                 priority        /* MSG_PRI_NORMAL or MSG_PRI_URGENT */
    )
int msgQReceive
    (
    FAST MSG_Q_ID       msgQId,         /* message queue from which to receive */
    char *              buffer,         /* buffer to receive message */
    UINT                maxNBytes,      /* length of buffer */
    int                 timeout         /* ticks to wait */
    )

2.信號量。VxWorks主要有三種類型的信號量:二進制信號量、互斥信號量和計數信號量,還提供POSIX信號量。信號量可以用來實現任務間通信、同步和互斥。

3.Vxworks任務的調度策略。主要是採用基於優先級的搶佔調度策略,同時還可使用輪轉(RR)調度算法。因爲基於優先級的調度可以很好的體現嵌入式操作系統的實時性需求,然後有一個缺陷是,如果多個同優先級任務需要共享一個處理器,某任務永遠佔有CPU,不阻塞,其他任務將沒有得到調度的機會,因此需要與RR調度算法結合使用。


實現原理

具體分析如下:

1.定義了三個消息隊列,包括一個請求隊列、兩個應答隊列。(如果需要實現雙工通信的話,必須有兩個隊列,一個隊列是無法雙工通信的)

2.定義了消息的結構體,包括任務的tid和發送的消息值。

3.定義了三個任務,包括一個服務端任務、兩個客戶端任務。

4.定義了兩個信號量,實現同步,控制程序的執行順序。首先根據優先級不同,客戶端任務將被先執行,採用信號量控制使客戶端一先向請求隊列發送三個消息,接着客戶端二向請求隊列發送三個消息。接下來服務端讀取請求隊列的消息,根據消息結構體中的tid值給相對應的客戶端的應答隊列反饋信息,信息內容爲客戶端發送信息內容值的平方。根據信號量的操作,客戶端一將先從應答隊列一讀取消息,客戶端一完成這一過程後,客戶端二才能從應答隊列二讀取消息。

5.刪除消息隊列和刪除信號量。


實現代碼

具體實現C/S通信的代碼如下:

/**
	@author zouliping
**/

#include "vxWorks.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "stdio.h"
#include "string.h"
#include "sysLib.h"
#include "semLib.h"

#define CLIENT_TASK_PRI 100
#define SERVER_TAST_PRI 101
#define TASK_STACK_SIZE 50000

typedef struct message
{
	int tid;
	int value;
}msg;

LOCAL MSG_Q_ID requestQ;
LOCAL MSG_Q_ID responseQ1;
LOCAL MSG_Q_ID responseQ2;

LOCAL BOOL notDone;
LOCAL int msgNum = 3;

LOCAL SEM_ID clientSem1;
LOCAL SEM_ID clientSem2;

LOCAL STATUS mClientTask1();
LOCAL STATUS mClientTask2();
LOCAL STATUS mServerTask();

STATUS CS(void)
{
	notDone = TRUE;
	/*創建應答和響應消息隊列*/
	if((requestQ = msgQCreate(2 * msgNum,sizeof(msg),MSG_Q_FIFO)) == NULL)
	{
        perror("Error in creating requestQ");
    }
    if((responseQ1 = msgQCreate(msgNum,sizeof(msg),MSG_Q_FIFO)) == NULL)
	{
        perror("Error in creating responseQ1");
    }
    if((responseQ2 = msgQCreate(msgNum,sizeof(msg),MSG_Q_FIFO)) == NULL)
	{
        perror("Error in creating responseQ2");
    }

    /*創建兩個信號量*/
	if ((clientSem1 = semBCreate (SEM_Q_PRIORITY, SEM_FULL)) == NULL)
	{ 
		perror ("Error in creating cSemId1 semaphore"); 
		return (ERROR);
	}
	if ((clientSem2 = semBCreate (SEM_Q_PRIORITY, SEM_FULL)) == NULL)
	{ 
		perror ("Error in creating cSemId2 semaphore"); 
		return (ERROR);
	}

    /*創建兩個client和一個server任務*/
    if(taskSpawn("tClientTask1",CLIENT_TASK_PRI,0,TASK_STACK_SIZE,(FUNCPTR)mClientTask1,0,0,0,0,0,0,0,0,0,0) == ERROR){
        perror("serverTask:Error in spawning mClientTask1");
        return (ERROR);
    }
    if(taskSpawn("tClientTask2",CLIENT_TASK_PRI,0,TASK_STACK_SIZE,(FUNCPTR)mClientTask2,0,0,0,0,0,0,0,0,0,0) == ERROR){
        perror("serverTask:Error in spawning mClientTask2");
        return (ERROR);
    }
    if(taskSpawn("tServerTask",SERVER_TAST_PRI,0,TASK_STACK_SIZE,(FUNCPTR)mServerTask,0,0,0,0,0,0,0,0,0,0) == ERROR){
        perror("serverTask:Error in spawning tServerTask");
        return (ERROR);
    }

    while (notDone)
    {
    	taskDelay (sysClkRateGet());
    }
	
	/*刪除消息隊列*/
	if(msgQDelete(requestQ) == ERROR || msgQDelete(responseQ1) == ERROR || msgQDelete(responseQ2) == ERROR)
	{
            perror("Error in deleting msgQ");
            return (ERROR);
    }

    /*刪除信號量*/
    if (semDelete(clientSem1) == ERROR || semDelete(clientSem2) == ERROR)
    {
		perror ("Error in deleting semaphore"); 
		return (ERROR);
	}

	return (OK);
} 

/*服務端任務*/
STATUS mServerTask(void)
{
	msg sendItem;
	msg receiveItem;
	int i;

	printf ("mServerTask started: task id = %#x.\n", taskIdSelf());


	for(i = 0;i < 2 * msgNum;i++)
	{
		/*從客戶端接受消息,取出請求隊列中的消息*/
        if((msgQReceive(requestQ,(char *)&receiveItem,sizeof(receiveItem),WAIT_FOREVER)) == ERROR)
        {
            perror("Error in receiving the message");
            return (ERROR);
        }
        else
		{
            printf("mServerTask:get message of value %d from mClientTask%d.\n",receiveItem.value,receiveItem.tid);
		}
	

		/*給兩個客戶端發送反饋消息*/
		sendItem.tid = taskIdSelf();
		sendItem.value = (receiveItem.value) * (receiveItem.value);
		if(receiveItem.tid == 1)
		{
			if((msgQSend(responseQ1,(char *)&sendItem,sizeof(sendItem),WAIT_FOREVER,MSG_PRI_NORMAL)) == ERROR){
	            perror("Error in sending the message to responsQ1");
	            return(ERROR);
	        }
	        else
	            printf("mServerTask sending to mClientTask1:server tid = %d, mClientTask1 getting message = %d \n",taskIdSelf(),sendItem.value);

		}
		else if(receiveItem.tid == 2)
		{
			if((msgQSend(responseQ2,(char *)&sendItem,sizeof(sendItem),WAIT_FOREVER,MSG_PRI_NORMAL)) == ERROR){
	            perror("Error in sending the message to responsQ1");
	            return(ERROR);
	        }
	        else
	            printf("mServerTask sending to mClientTask2:server tid = %d, mClientTask2 getting message = %d \n",taskIdSelf(),sendItem.value);
		}
	}

	semGive(clientSem1);

	return (OK);
}

/*客戶端一任務*/
STATUS mClientTask1(void)
{
	msg sendItem;
	msg receiveItem;
	int i;

	printf ("mClientTask1 started: task id = %#x.\n", taskIdSelf());

	semTake (clientSem1, WAIT_FOREVER);

	/*client1發送三個消息到服務端*/
	for(i = 0;i < msgNum;i++)
	{
		sendItem.tid = 1;
		sendItem.value = i;

		if((msgQSend(requestQ,(char *)&sendItem,sizeof(sendItem),WAIT_FOREVER,MSG_PRI_NORMAL)) == ERROR)
		{
            perror("Error in sending the message");
            return(ERROR);
        }
        else
            printf("mclientTask1 sending message to server: tid = %d,sending message = %d.\n",taskIdSelf(),i);
	}

	semGive(clientSem2);

	semTake (clientSem1, WAIT_FOREVER);

	/*從服務端接受消息*/
	for(i = 0;i < msgNum;i++)
	{
		if((msgQReceive(responseQ1,(char *)&receiveItem,sizeof(receiveItem),WAIT_FOREVER)) == ERROR)
		{
            perror("Error in sending the message");
            return(ERROR);
        }
        else
            printf("mclientTask1 receiving message from server: tid = %d,receiving message =  %d.\n",receiveItem.tid,receiveItem.value);
	}

	semGive(clientSem2);

	return (OK);
}

/*客戶端二任務*/
STATUS mClientTask2(void)
{
	msg sendItem;
	msg receiveItem;
	int i;

	printf ("mClientTask2 started: task id = %#x.\n", taskIdSelf());
	semTake (clientSem2, WAIT_FOREVER);

	/*client2發送三個消息到服務端*/
	for(i = 0;i < msgNum;i++)
	{
		sendItem.tid = 2;
		sendItem.value = i;

		if((msgQSend(requestQ,(char *)&sendItem,sizeof(sendItem),WAIT_FOREVER,MSG_PRI_NORMAL)) == ERROR)
		{
            perror("Error in sending the message");
            return(ERROR);
        }
        else
            printf("mclientTask2 sending message to server: tid = %d,sending message = %d.\n",taskIdSelf(),i);
	}

	semTake (clientSem2, WAIT_FOREVER);

	/*從服務端接受消息*/
	for(i = 0;i < msgNum;i++)
	{
		if((msgQReceive(responseQ2,(char *)&receiveItem,sizeof(receiveItem),WAIT_FOREVER)) == ERROR)
		{
            perror("Error in sending the message");
            return(ERROR);
        }
        else
            printf("mclientTask2 receiving message from server: tid = %d,receiving message = %d.\n",receiveItem.tid,receiveItem.value);
	}

	notDone = FALSE;

	return (OK);
}

運行結果

代碼運行結果如下:

在Tornado中的 vxsim打印結果信息

windview演示結果



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章