Program:
Program ideas:
Write the functions of the client and the server respectively, and create two clients and one server in the Director's office. Considering the actual situation, the server should have a high priority and use the taskspawn function to create server tasks. Then, wait for the client to obtain a response from the server, delete the queue, and end the program. To demonstrate the client request and server response process, this experiment sends a value when sending the client, which is given when the task is created, and the value is added when each request is made, after obtaining the value, the server increases the value and returns it to the corresponding response queue based on the Client ID. The client function sends data based on the size of the Request queue, and then waits for the response queue to receive the returned results. The waiting queue in the server function is not empty. The request is obtained and returned to the corresponding response queue.
Key code:
main.h#ifndef MAIN_H_INCLUDED#define MAIN_H_INCLUDED#include "vxWorks.h"#include "semLib.h"#include "taskLib.h"#include "msgQLib.h"#include "sysLib.h"#include "stdio.h"#define CLIENT_TASK_PRI 99#define SERVER_TASK_PRI 98#define TASK_STACK_SIZE 5000struct msg{ int id; int value;};LOCAL MSG_Q_ID requestQId;LOCAL MSG_Q_ID response1QId;LOCAL MSG_Q_ID response2QId;LOCAL BOOL notDone;LOCAL int numMsg = 3;LOCAL STATUS clientTask (int cid, int value);LOCAL STATUS serverTask(void);#endif // MAIN_H_INCLUDED
# Include "Main. H "status clienttask (int cid, int value) {int I, j, k; struct MSG request_msg, response_msg; printf (" clienttask started: cid = % d \ n ", CID); for (I = 0; I <nummsg; I ++) {request_msg.id = CID; request_msg.value = value + I;/* semtake (request_semmutex, wait_forever ); */If (msgqsend (requestqid, (char *) & request_msg, sizeof (request_msg), wait_forever, msg_pri_normal) = Error) {perror (" Error in sending the message to request queue \ n "); Return (error);} else {printf (" clienttask: cid = % d, value = % d \ n ", CID, value + I);}/* semgive (request_semmutex); */}/* receive data from responseq */if (1 = CID) {for (j = 0; j <nummsg; j ++) {/* semtake (responsesponsemmutex, wait_forever); */If (msgqreceive (response1qid, (char *) & response_msg, sizeof (response_msg ), wait_forever) = Error) {perror ("erro R in processing ing the response1 message \ n "); Return (error);} else {printf (" clienttask: Get MSG of Value % d from cid = % d \ n ", response_msg.value, response_msg.id);}/* semgive (responseeclipsemmutex); */} else if (2 = CID) {for (k = 0; k <nummsg; k ++) {/* semtake (response, wait_forever); */If (msgqreceive (response2qid, (char *) & response_msg, sizeof (response_msg), wait_forever) = erro R) {perror ("error in processing the response2 message \ n"); Return (error);} else {printf ("clienttask: get MSG of Value % d from cid = % d \ n ", response_msg.value, response_msg.id);}/* semgive (response2_semmutex); */} else {printf (" clienttask: CID error! \ N ") ;}notdone = false; Return (OK) ;}status servertask (void) {int I; struct MSG response_msg; printf (" \ nservertask started \ n "); for (I = 0; I <nummsg * 2; I ++) {/* semtake (request_semmutex, wait_forever); */If (msgqreceive (requestqid, (char *) & response_msg, sizeof (response_msg), wait_forever) = Error) {perror ("error in processing ing the message \ n"); Return (error );} else {printf ("servertask: Get MSG of Value % d from cid = % d \ n", response_msg.value, response_msg.id);}/* semgive (request_semmutex ); * // * after the obtained value is added, the CID is sent to the corresponding response sequence */response_msg.value + = 1; if (response_msg.id = 1) {/* semtake (responsew.semmutex, wait_forever); */If (msgqsend (response1qid, (char *) & response_msg, sizeof (response_msg), wait_forever, msg_pri_normal) = Error) {perror ("error in sending the message to response1 queue \ n"); Return (error);} else {printf ("servertask sending to response Q1: value = % d \ n ", response_msg.value);}/* semgive (response1_semmutex); */} else if (response_msg.id = 2) {/* semtake (response, wait_forever ); */If (msgqsend (response2qid, (char *) & response_msg, sizeof (response_msg), wait_forever, msg_pri_normal) = Error) {perror ("error in sending the message to response2 queue \ n"); Return (error);} else {printf ("servertask sending to response Q2: value = % d \ n ", response_msg.value);}/* semgive (response2_semmutex); */} else {printf (" error in response_msg, the id = % d \ n ", response_msg.id) ;}} return (OK) ;}status main () {notdone = true;/* response = sembcreate (sem_q_fifo, sem_full); responseeclipsemmutex = sembcreate (sem_q_fifo, sem_full ); response2_semmutex = sembcreate (sem_q_fifo, sem_full); */If (requestqid = msgqcreate (nummsg * 2, sizeof (struct MSG), msg_q_fifo) = NULL) {perror ("error in creating requestq"); Return (error);} If (response1qid = msgqcreate (nummsg, sizeof (struct MSG), msg_q_fifo) = NULL) {perror ("error in creating response1q"); Return (error);} If (response2qid = msgqcreate (nummsg, sizeof (struct MSG), msg_q_fifo) = NULL) {perror ("error in creating response2q"); Return (error);} If (taskspawn ("tservertask", server_task_pri, 0, task_stack_size, (funcptr) servertask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = Error) {perror ("servertask: Error in spawning servertask"); Return (error );} if (taskspawn ("tclienttask", client_task_pri, 0, task_stack_size, (funcptr) clienttask, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = Error) {perror ("clienttask: Error in spawning clienttask1"); Return (error);} If (taskspawn ("tclienttask", client_task_pri, 0, task_stack_size, (funcptr) clienttask, 2, 10, 0, 0, 0, 0, 0, 0, 0) = Error) {perror ("clienttask: Error in spawning clienttask2 "); return (error) ;}while (notdone) {taskdelay (sysclkrateget ();} If (msgqdelete (requestqid) = Error | msgqdelete (response1qid) = Error | msgqdelete (response2qid) = Error) {perror ("error in deleting msgqs"); Return (error);} return (OK );}
Experiment results:
It can be seen that the server task is first entered, and then the client task is entered. After the client sends a message to the Request queue, the server immediately obtains the value because the server has a high priority, therefore, the printed message is printed after the server is blocked, and it can be seen that serverl immediately sends a message to the corresponding response queue. At this time, the value is more than the value sent by the client, the program design was followed. Until all requests of Client1 are responded, Client1 gets the value after adding one from its own response queue, and then Client2 does the same.
The following shows the windview demo result:
The first figure shows that T1 is the case where the supervisor creates three tasks and switches to the server. However, the server is blocked because the request queue is empty and switches to Client1, when Client1 has a request, it switches to the server and responds accordingly. This is also true for Client2.
After a while, because the main program has been waiting for the client to receive the response queue message, it can be seen from the end that the request queue and response queue 1 and response queue 2 have been deleted, the program ends.
Problems:
1. The single line comment "//" in C language cannot be used, and compilation fails.
2. When binary semaphore is used at the beginning, only one task in the queue can be sent or accepted, resulting in a deadlock. Before sending, take the request queue and send it. Because the server has a high priority, the semaphore has not been released yet, and the server receives the request queue and cannot obtain the semaphore, cause a deadlock that persists.
3. In the beginning, we did not consider the actual situation. First, we created Client1 and Client2, and set the priority to the same. In fact, we should first start the server to allow client requests, so we should change the order, create a server task first.
4. Select the task state transition when observing with windview. The default context switch cannot be used at the beginning to observe the expected results. After that, you can see the relevant information by hovering over the mouse, which is very convenient.