Basic example message queues reader and writer

  • In this program, you are going to learn

  • How to open a message queue ?

  • How to get/set message queue attributes ?

  • How to receive a message from a message queue?

  • How to send a message to a message queue?

Let us answer few basic questions in this message queues

What does mq_open do in this context?

Why use O_CREAT | O_RDWR as flags?

What is the significance of the 0666 permission parameter?

Can mq_open open an existing queue?

What happens if the queue with queue_name does not exist?

How does mq_open handle errors during queue creation?

Why pass NULL as the last parameter?

Can multiple processes open the same message queue?

What is the lifetime of the message queue created with mq_open?

How do I unlink (delete) a message queue created with mq_open?

https://www.plantuml.com/plantuml/svg/LK-x3i8m3Dpp5MP1hOWGB1rWAGAs2gGAn5YbnIsLaZxYX07nyRXH5xOxtyDsIavPvuqM2_T2Wq23gb2hKWH1xCnOz0DsqUZHOz4fWnAknJ4_7sxmPPIV7hc4JP8a4YxtB8lt8TEWKyxPo8mIbXEQvnOhRDyOvgMlQxGI9ddDcg66sW_-zH1sps0sIAGQ5ibPpVVCF8OLR7d_RAzqJrCvKtBz85AEytC_
  • There are many functions used in message queues. We can classify those functions based on functionalities.

    • mq_open

    • mq_getattr

    • mq_receive

    • mq_send

    • mq_close

  • mq_open is used to open message queues. For example,

mq = mq_open(queue_name, O_CREAT | O_RDWR, 0666, NULL);
  • mq_getattr is used to get message queue attributes. For example,

mq_getattr(mq, &attr);
  • mq_receive is used to receive a message from a message queue. For example,

ret = mq_receive(mq, buffer, attr.mq_msgsize, NULL);;
  • mq_send is used to send a message to a message queue. For example,

ret = mq_send(mq, message, strlen(message) + 1, 0);
  • mq_close is used to close the opened message queues. For example,

mq_close(mq);
  • See the full program below,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>
#include <unistd.h>
#include <signal.h>

int main(void) 
{
  struct mq_attr attr;
  char* buffer;
  int ret;
  mqd_t mq;
  const char* queue_name = "/my_queue";
  const char* message = "Hello, Writer!";

  mq = mq_open(queue_name, 
  O_CREAT | O_RDWR, 0666, NULL);
  
  if (mq == (mqd_t)-1) {
    perror("mq_open");
    return -1;
  }

  ret = mq_getattr(mq, &attr);
 
  if (ret < 0) {
    perror("mq_getattr");
    (void)close(mq);
    return -2;
  }

  buffer = (char*)malloc(
  attr.mq_msgsize);

  if (buffer == NULL) {
    perror("malloc");
    (void)close(mq);
    return -3;
  }

  ret = mq_receive(mq, buffer, 
  attr.mq_msgsize, NULL);

  if (ret < 0) {
    perror("mq_receive");
    (void)close(mq);
    return -4;
  }

  printf("Received message: %s\n",
  buffer);
  free(buffer);

  ret = mq_send(mq, message, 
  strlen(message) + 1, 0);
 
  if (ret < 0) {
    perror("mq_send");
    (void)close(mq);
    return -5;
  } else {
    printf("messageSent = %s\n", 
    message);
  }
  (void)mq_close(mq);

  return 0;
}

1$ gcc -o reader reader.c -lrt
2
3$ sudo ./reader
4
5Received message: Hello, reader!
6messageSent = Hello, Writer!
https://www.plantuml.com/plantuml/svg/HO-x3e9044Nx_OgnCH0tHXiARJ1gHpGX6akom80akpnsTYcC7-z0IEpkt3jd7Z4vPPqtMgpS6mq2zQf0hN8n1-9WXgphiGq6ZnwpLXcKSC_EwVNqW2-hzF9A9UoYA99mUoP9U9mPmhOCp231896g6I9dDSzPwX0si6TkQQ_HAUViJAmdjVWM2sn6dFtSLnLQ2LEyvSnGJSq7_sk3iMlAa9D2TpGnR9BhUX7pCVpY3m==
  • There are many functions used in message queues. We can classify those functions based on functionalities.

    • mq_open

    • mq_send

    • mq_getattr

    • mq_receive

    • mq_close

  • mq_open is used to open message queues. For example,

mq = mq_open(queue_name, O_CREAT | O_RDWR, 0666, NULL);
  • mq_send is used to send a message to a message queue. For example,

ret = mq_send(mq, message, strlen(message) + 1, 0);
  • mq_getattr is used to get message queue attributes. For example,

ret = mq_getattr(mq, &attr);
  • mq_receive is used to receive a message from a message queue. For example,

ret = mq_receive(mq, buffer, attr.mq_msgsize, NULL);;
  • mq_close is used to close the opened message queues. For example,

mq_close(mq);
  • See the full program below,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>
#include <unistd.h>
#include <signal.h>

int main(void) 
{
  mqd_t mq;
  int ret;
  char *buffer;
  const char* queue_name = "/my_queue";
  const char* message = "Hello, reader!";
  struct mq_attr attr;

  mq = mq_open(queue_name, 
  O_CREAT | O_RDWR, 0666, NULL);
  
  if (mq == (mqd_t)-1) {
    perror("mq_open");
    return -1;
  }

  ret = mq_send(mq, message, 
  strlen(message) + 1, 0);
 
  if (ret < 0) {
    perror("mq_send");
    (void)close(mq);
    return -2;
  } else {
    printf("messageSent = %s\n", 
    message);
  }

  ret = mq_getattr(mq, &attr);
 
  if(ret < 0) {
    perror("mq_getattr");
    (void)close(mq);
    return -3;
  }  

  buffer = (char*)malloc(
  attr.mq_msgsize);

  if (buffer == NULL) {
    perror("malloc");
    (void)close(mq);
    return -4;
  }

  memset(buffer, 0, 
  sizeof(buffer));
  
  ret = mq_receive(mq, buffer, 
  attr.mq_msgsize, NULL);

  if (ret < 0) {
    perror("mq_receive");
    (void)close(mq);
    return -5;
  }

  printf("Received message: %s\n", 
  buffer);
  free(buffer);     
  (void)mq_close(mq);

  return 0;
}

1$ gcc -o writer writer.c -lrt
2
3$ sudo ./writer
4
5messageSent = Hello, reader!
6Received message: Hello, Writer!
https://www.plantuml.com/plantuml/svg/LP1DJyCm38Rl-HNcWXerGkFImmhI9gYuR22r88vLrdbTfAGVSJe4uiVZHBjmyiVx-BMJ3GNjm-Aik0bdT0WqwGwjFeWaYBMRst728PiNNB0Tj4C5R-rJNMtVuPUp-lcpLh0gYaB1wyTk9yiqqsFG8VZCpGfkOnRx1XvXLOglix48sJKOUE31VRklccRxKZLIWY78lf5aSlBOeRbWSZeifnDw1T7mZZL7FPaV_BUPS3Wcs26Hxbcau2s_u5fBoE6UBuvudfjIC9zE4UliCfgZP8_EZXGtCaDXdCI66VwZFm==
  • There are many functions used in message queues. We can classify those functions based on functionalities.

    • mq_open

    • mq_getattr

    • mq_receive

    • mq_send

    • mq_close

  • mq_open is used to open message queues. For example,

mq = mq_open(queue_name, O_CREAT | O_RDWR, 0666, NULL);
  • mq_getattr is used to get message queue attributes. For example,

mq_getattr(mq, &attr);
  • mq_receive is used to receive a message from a message queue. For example,

ret = mq_receive(mq, buffer, attr.mq_msgsize, NULL);;
  • mq_send is used to send a message to a message queue. For example,

ret = mq_send(mq, message, strlen(message) + 1, 0);
  • mq_close is used to close the opened message queues. For example,

mq_close(mq);
  • See the full program below,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>
#include <unistd.h>
#include <signal.h>

#define NUM_MESSAGES 10

int main(void) 
{
  struct mq_attr attr;
  char* buffer;
  int ret, i;
  mqd_t mq;
  const char* queue_name = "/my_queue";
  const char* message = "Hello, Writer!";

  mq = mq_open(queue_name, 
  O_CREAT | O_RDWR, 0666, NULL);
  
  if (mq == (mqd_t)-1) {
    perror("mq_open");
    return -1;
  }

  ret = mq_getattr(mq, &attr);
 
  if (ret < 0) {
    perror("mq_getattr");
    (void)close(mq);
    return -2;
  }

  i = 0;
  while (i < NUM_MESSAGES) {
  buffer = (char*)malloc(
  attr.mq_msgsize);

  if (buffer == NULL) {
    perror("malloc");
    (void)close(mq);
    return -3;
  }

  ret = mq_receive(mq, buffer, 
  attr.mq_msgsize, NULL);

  if (ret < 0) {
    perror("mq_receive");
    (void)close(mq);
    return -4;
  }

  printf("Received message: %s\n",
  buffer);
  free(buffer);

  ret = mq_send(mq, message, 
  strlen(message) + 1, 0);
 
  if (ret < 0) {
    perror("mq_send");
    (void)close(mq);
    return -5;
  } else {
    printf("messageSent = %s\n", 
    message);
  }
  ++i;
  }

  (void)mq_close(mq);

  return 0;
}

 1$ gcc -o reader reader.c -lrt
 2
 3$ sudo ./reader
 4
 5Received message: Hello, reader!
 6messageSent = Hello, Writer!
 7Received message: Hello, reader!
 8messageSent = Hello, Writer!
 9Received message: Hello, reader!
10messageSent = Hello, Writer!
11Received message: Hello, reader!
12messageSent = Hello, Writer!
13Received message: Hello, reader!
14messageSent = Hello, Writer!
15Received message: Hello, reader!
16messageSent = Hello, Writer!
17Received message: Hello, reader!
18messageSent = Hello, Writer!
19Received message: Hello, reader!
20messageSent = Hello, Writer!
21Received message: Hello, reader!
22messageSent = Hello, Writer!
23Received message: Hello, reader!
24messageSent = Hello, Writer!
https://www.plantuml.com/plantuml/svg/HP1DIyGm48Rl-HNZHH8QPBtqq2hieiNBhaAhU2pPxcmtqFGZawue_dYdeU0fatcVp3DaIy7uCBjEt8GBEWGQJOETEOeOYCnDzJ1YBwSPPwnxur33M_rK5hjt-EMgVFuiDMpIDDNm-h7Vgrna5XvXauklY-qGv7fOU63WK1-Agjgz59LIO0daDvAA5iB-9DsamI6HQLb3mNTiNkyA4hXdqo9WlCLWGl3nnUrIhNsF3TehnlvnFf_HQrZYEyuSjMH_y7_H9B6vO6zSKMJoEjYJOh3f1bf6C4DX6CMM6VwZFm==
  • There are many functions used in message queues. We can classify those functions based on functionalities.

    • mq_open

    • mq_send

    • mq_getattr

    • mq_receive

    • mq_close

  • mq_open is used to open message queues. For example,

mq = mq_open(queue_name, O_CREAT | O_RDWR, 0666, NULL);
  • mq_send is used to send a message to a message queue. For example,

ret = mq_send(mq, message, strlen(message) + 1, 0);
  • mq_getattr is used to get message queue attributes. For example,

ret = mq_getattr(mq, &attr);
  • mq_receive is used to receive a message from a message queue. For example,

ret = mq_receive(mq, buffer, attr.mq_msgsize, NULL);;
  • mq_close is used to close the opened message queues. For example,

mq_close(mq);
  • See the full program below,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>
#include <unistd.h>
#include <signal.h>

int main(void) 
{
  mqd_t mq;
  int ret;
  char *buffer;
  const char* queue_name = "/my_queue";
  const char* message = "Hello, reader!";
  struct mq_attr attr;

  mq = mq_open(queue_name, 
  O_CREAT | O_RDWR, 0666, NULL);
  
  if (mq == (mqd_t)-1) {
    perror("mq_open");
    return -1;
  }

  ret = mq_send(mq, message, 
  strlen(message) + 1, 0);
 
  if (ret < 0) {
    perror("mq_send");
    (void)close(mq);
    return -2;
  } else {
    printf("messageSent = %s\n", 
    message);
  }

  ret = mq_getattr(mq, &attr);
 
  if(ret < 0) {
    perror("mq_getattr");
    (void)close(mq);
    return -3;
  }  

  buffer = (char*)malloc(
  attr.mq_msgsize);

  if (buffer == NULL) {
    perror("malloc");
    (void)close(mq);
    return -4;
  }

  memset(buffer, 0, 
  sizeof(buffer));
  
  ret = mq_receive(mq, buffer, 
  attr.mq_msgsize, NULL);

  if (ret < 0) {
    perror("mq_receive");
    (void)close(mq);
    return -5;
  }

  printf("Received message: %s\n", 
  buffer);
  free(buffer);     
  (void)mq_close(mq);

  return 0;
}

 1$ gcc -o writer writer.c -lrt
 2
 3$ sudo ./writer
 4
 5messageSent = Hello, reader!
 6Received message: Hello, Writer!
 7messageSent = Hello, reader!
 8Received message: Hello, Writer!
 9messageSent = Hello, reader!
10Received message: Hello, Writer!
11messageSent = Hello, reader!
12Received message: Hello, Writer!
13messageSent = Hello, reader!
14Received message: Hello, reader!
15messageSent = Hello, reader!
16Received message: Hello, reader!
17messageSent = Hello, reader!
18Received message: Hello, reader!
19messageSent = Hello, reader!
20Received message: Hello, reader!
21messageSent = Hello, reader!
22Received message: Hello, reader!
23messageSent = Hello, reader!
24Received message: Hello, reader!

Message queues API

Learning

mq_open

creates a new message queue or opens an existing one, depending on the specified flags and parameters.

mq_getattr

is employed to obtain the attributes of an open message queue, including its current state and configuration.

mq_receive

receiving (reading) messages from a message queue.

mq_send

sending (writing) messages to a message queue.

mq_close

used to close a message queue descriptor.