Custom Message Queuing for Linux programming

Source: Internet
Author: User
Tags message queue semaphore

typedef struct MSG_HDR_S  {      uint32 msg_type;      UInt32 Msg_len;      UInt32 msg_src;      UInt32 msg_dst;      } msg_hdr_t;    typedef struct MSG_S  {      msg_hdr_t Hdr;      Uint8 data[100];  } msg_t;
Here is an explanation of the message format content I designed:
    • Msg_type: Flags The message type, and when the message receiver sees the msg_type, he knows what he's going to do.
    • Msg_len: Message length, to be extended, temporarily useless (later extended to a variable length message)
    • MSG_SRC: The source address of the message, which is the initiator of the message
    • MSG_DST: The destination of the message, which is the recipient of the message
    • DATA[100]: Message drops the amount of information that can be carried outside the message header, defined as 100 bytes
By the message data structure can be known, this message is fixed length, of course, can also be implemented as a variable length message, but now do not implement, today, the fixed-length message is implemented, and then perfect the variable-length message. Second, construct the cyclic queueA queue can be implemented by a linked list or by an array, where the loop linked list implemented by the array is used as the queue model for our message queue.
typedef struct QUEUE_S {int head;      int rear;      sem_t sem;  msg_t Data[queue_size];    }queue_t; int Msgqueueinit (queue_t* Q) {if (!          Q) {printf ("Invalid queue!\n");      return-1;      } q->rear = 0;      Q->head = 0;      Sem_init (&q->sem, 0, 1);      return 0; } int Msgdequeue (queue_t* Q, msg_t* Msg) {if (!          Q) {printf ("Invalid queue!\n");      return-1;          } if (q->rear = = q->head)//only One consumer,no need to lock head {printf ("Empty queue!\n");      return-1;      } memcpy (MSG, & (Q->data[q->head)), sizeof (msg_t));      Q->head = (q->head+1)%queue_size;           return 0; } int Msgenqueue (queue_t* Q, msg_t* Msg) {if (Q->head = = (q->rear+1)%queue_size) {printf ("Fu          ll queue!\n ");      return-1;      } sem_wait (&q->sem);     memcpy (& (Q->data[q->rear]), MSG, sizeof (msg_t)); Q->rear = (q->rear+1)%queue_size;      Sem_post (&q->sem);  return 0;  }
The implementation of the cyclic queue must be familiar to everyone, but here are a few things to note:
    • A semaphore or lock should be added to the queue to secure mutually exclusive access at the time of entry, as multiple messages may be queued at the same time, overwriting their queue nodes
    • The semaphore here is only for the incoming team and not for the team, the reason is that there is only one message processor, there is no mutually exclusive case

Third, construct the message processor

 if (pthread_create (&handler_thread_id, NULL, (void*) Msg_handler, null)) {printf ("Create handler thread fail      !\n ");          return-1;      } void Msg_printer (msg_t* msg) {if (!msg) {return;      } printf ("%s:i has recieved a message!\n", __function__); printf ("%s:msgtype:%d msg_src:%d dst:%d\n\n",__function__,msg->hdr.msg_type,msg->hdr.msg_src,msg->    HDR.MSG_DST);  } void Msg_handler () {sleep (5);          Let's wait 5s when starts while (1) {msg_t Msg;          memset (&msg, 0, sizeof (msg_t));          int res = Msgdequeue ((queue_t*) &msgqueue, &msg);              if (res! = 0) {sleep (10);          Continue          } msg_printer (&MSG);      Sleep (1); }  }
I create a thread in the process to handle Message Queuing messages as a message processor (handler), and when you enter the thread, wait 5 seconds for the producer to drop a message in the queue before starting the message processing. When the queue does not have the message to be desirable, rest for 10 seconds, and then fetch the message. The message processing here is simple, I simply print the message I received, proving that the message I received was Cheng to me by the other line. Of course, you can also extend the functionality here to further decide what to do depending on the type of message being received. Like what:
Enum Msg_type  {      go_home,      go_to_bed,      go_to_lunch,      Go_to_cinama,      go_to_school,      go_ Dateing,      GO_TO_WORK,//6  };    void Handler ()  {      switch (msgtype)      {case          go_home:go_home ();          Case go_to_bed:  go_to_bed ();          .......      }  }

Here the handler is a simple state machine, according to the given message type (event) to do specific things, to promote the rotation of the state machine.

Iv. Construction of Message producers

if (pthread_create (&thread1_id, NULL, (void*) msg_sender1, null)) {printf ("Create Thread1 fail!\n");  return-1;      } if (Pthread_create (&thread2_id, NULL, (void*) msg_sender2, null)) {printf ("Create thread2 fail!\n");  return-1;      } if (Pthread_create (&thread3_id, NULL, (void*) Msg_sender3, null)) {printf ("Create Thread3 fail!\n");  return-1;      } void Msg_sender1 () {int i = 0;          while (1) {if (i >) {i = 0;          } msg_t MSG;          Msg.hdr.msg_type = i++;          MSG.HDR.MSG_SRC = THREAD1;          MSG.HDR.MSG_DST = HANDLER;          Msgenqueue ((queue_t*) &msgqueue, &msg);          printf ("%s:thread1 send a message!\n", __function__);      Sleep (1);      }} void Msg_sender2 () {int i = 0;          while (1) {if (i >) {i = 0;          } msg_t MSG;          Msg.hdr.msg_type = i++; Msg.hdr.MSG_SRC = THREAD2;          MSG.HDR.MSG_DST = HANDLER;          Msgenqueue ((queue_t*) &msgqueue, &msg);          printf ("%s:thread2 send a message!\n", __function__);      Sleep (1);      }} void Msg_sender3 () {int i = 0;          while (1) {if (i >) {i = 0;          } msg_t MSG;          Msg.hdr.msg_type = i++;          MSG.HDR.MSG_SRC = THREAD3;          MSG.HDR.MSG_DST = HANDLER;          Msgenqueue ((queue_t*) &msgqueue, &msg);          printf ("%s:thread3 send a message!\n", __function__);      Sleep (1); }  }

Here I create three threads to simulate message producers, each of which writes messages to the message queue every 1 seconds.

Five, run up and see

First put the complete code: MSG_QUEUE.C:
  1 #include <stdio.h> 2 #include <pthread.h> 3 #include <semaphore.h> 4 #include <unistd.h&    Gt    5 #include <string.h> 6 #include "msg_def.h" 7 8 queue_t Msgqueue;   9 int main (int argc, char* argv[]) one {n-int ret;   pthread_t thread1_id;   pthread_t thread2_id;   pthread_t thread3_id;   pthread_t handler_thread_id;   + ret = Msgqueueinit ((queue_t*) &msgqueue);   if (ret! = 0) (+ return-1;         (Pthread_create (&handler_thread_id, NULL, (void*) Msg_handler, null)) 25 {26   printf ("Create handler thread fail!\n");           return-1;         if (pthread_create (&thread1_id, NULL, (void*) msg_sender1, null)) 32 {33   printf ("Create Thread1 fail!\n");   return-1; if (pthread_create (&thread2_id, NULL, (void*) msg_sender2, NULL) ("Create Thread2 fail!\n")   return-1; if (pthread_create (&thread3_id, NULL, (void*) Msg_sender3, NULL))   INTF ("Create Thread3 fail!\n");   return-1;   (+ 1) (1); "   0; (Msgqueueinit) (queue_t* Q) + (!)   Q) ("Invalid queue!\n")   return-1;   q->rear = 0;   Q->head = 0;   Sem_init (&q->sem, 0, 1);       return 0; "Msgdequeue" (queue_t* Q, msg_t* Msg).   Q) Invalid ("queue!\n");   return-1; (Q->rear = = q->head)//only One cosumer,no need to lock head ("EMP   Ty queue!\n ");   return-1;    85 } memcpy (MSG, & (Q->data[q->head)), sizeof (msg_t));   Q->head = (q->head+1)%queue_size;          return 0;   Msgenqueue (queue_t* Q, msg_t* Msg) (Q->head = = (q->rear+1)%queue_size)   ("Full queue!\n");   return-1;  98} sem_wait (&AMP;Q-&GT;SEM);  memcpy (& (Q->data[q->rear)), MSG, sizeof (msg_t));  101 Q->rear = (q->rear+1)%queue_size;  102 Sem_post (&AMP;Q-&GT;SEM);  103 return 0;  104} 106 void Msg_printer (msg_t* msg) 107 {108 if (!MSG) 109 {return;  111} ("%s:i has recieved a message!\n", __function__); 113 printf ("%s:msgtype:%d msg_src:%d dst:%d\n\n", __FUNCTION__,MSG-&GT;HDR.MSG_TYPE,MSG-&GT;HDR.MSG_SRC,MSG-&GT;HD  R.MSG_DST);  117 int Msg_send () 118 {119-msg_t msg;  121 Msg.hdr.msg_type = Go_home; 122 MSG.HDR. msg_src = THREAD1;  123 MSG.HDR.MSG_DST = HANDLER;      124 return Msgenqueue ((queue_t*) &msgqueue, &msg);  126} 127 Msg_handler () 129 {[5];  Let's wait 5s when the starts 131 while (1) 133 msg_t MSG;  134 memset (&msg, 0, sizeof (msg_t));  135 int res = Msgdequeue ((queue_t*) &msgqueue, &msg);  136 if (res! = 0) 137 {138 sleep (10);  139 continue;  141 Msg_printer (&msg);  142 sleep (1);  143} 144} 145 146 147 void Msg_sender1 () 148 {149 int i = 0;  while (1) 151 {if (i >) 153 {154 i = 0;  155} 156 msg_t MSG;  157 msg.hdr.msg_type = i++;  158 msg.hdr.msg_src = THREAD1;  159 MSG.HDR.MSG_DST = HANDLER;  Msgenqueue ((queue_t*) &msgqueue, &msg); 161 printf ("%s:thread1 Send a MessaGe!\n ", __function__);  162 sleep (1);  163} 164} 165 166 void Msg_sender2 () 167 {168 int i = 0;  169 while (1) 171 if (i >) 172 {173 i = 0;  174} 175 msg_t MSG;  176 msg.hdr.msg_type = i++;  177 msg.hdr.msg_src = THREAD2;  178 MSG.HDR.MSG_DST = HANDLER;  179 Msgenqueue ((queue_t*) &msgqueue, &msg);  message!\n printf ("%s:thread2 send a", __function__);  181 sleep (1);  182} 183} 184 185 void Msg_sender3 () 186 {187 int i = 0;  188 while (1) 189 {if (i >) 191 {192 i = 0;  193} 194 msg_t MSG;  195 Msg.hdr.msg_type = i++;  196 msg.hdr.msg_src = THREAD3;  197 MSG.HDR.MSG_DST = HANDLER;  198 Msgenqueue ((queue_t*) &msgqueue, &msg);  199 printf ("%s:thread3 send a message!\n", __function__);  Sleep (1); 201} 202} 

Msg_def.h:

 1 #include <stdio.h> 2 #include <pthread.h> 3 #include <semaphore.h> 4 5 typedef unsigned CHAR   Uint8;   6 typedef unsigned short unit16;   7 typedef unsigned int uint32;  8 9 #define Queue_size a typedef struct MSG_HDR_S {UInt32 msg_type;  UInt32 Msg_len;  UInt32 msg_src;      UInt32 MSG_DST;  }msg_hdr_t;  typedef struct MSG_S (msg_hdr_t Hdr);  Uint8 data[100];  msg_t};  The typedef struct QUEUE_S-V int head;  rear int;  sem_t sem;  msg_t Data[queue_size];  }queue_t;  The typedef struct QUEUE_S queuenode; Msg_type enum, Go_home, go_to_bed, Go_to_lunch, Go_to_cinama, go_to_s  Chool, Go_dateing, GO_TO_WORK,//6 44};  src_addr enum {THREAD1, THREAD2, THREAD3, Wuyi HANDLER, 52};  Msgqueueinit Int (queue_t* Q); INT Msgdequeue (queue_t* Q, msg_t* MSG);  Msgenqueue Int (queue_t* Q, msg_t* MSG);  Msg_handler void ();  Msg_sender1 void ();  void Msg_sender2 ();  Msg_sender3 void ();  msg_printer void (msg_t* msg); msg_send Int ();

Look at the phenomenon of running: finish! now the architecture of the message queue in the process is very practical in practical engineering (of course, the framework of the actual project is much more complex and robust), and many projects need this event-driven idea to ensure that every request can be executed in a non-flocculation manner, so this framework is also useful , especially with the state machine is very suitable!

Custom Message Queuing for Linux programming

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.