C Programming

POSIX Message Queues with C Programming

POSIX Inter-process Communication (IPC)

IPC is used for real-time extensions. These message queues are a part of Linux. These calls are used as a standard now but might be a part of contemporary versions. These calls are easy to implement with a much cleaner interface.

POSIX Message Queues in Linux

V message queues in a Linux system are identified using keys that are obtained using ftok calls. These POSIX message queues usually use name strings. In Linux systems, POSIX queues are called strings. These strings are considered to start with / and then have other characters.  Processes that follow and know the name of the queue name with appropriate rights can send or receive messages to and from the queue. This will help in performing important functionalities.

What Are POSIX Message Queue Calls?

POSIX message queues must link with any library that exits for real. Following are a few calls that are used:

librt uses the compiler option -lrt

Call names begin with the mq_prefix

The details of Queue Calls are discussed below:

>> mq_open, mq_close

This function is used to open up a POSIX queue.

Mq_open is a function that is used to call the name of the queue. The next parameter is a flag used to receive the messages. O_WRONLY is used to send messages, and O_RDWR is used to send and receive operations within the queue. Users can use the O_NONBLOCK flag to specify the queue to the non-blocking mode and mq_send and mq_receive to send and receive data in a queue.

Syntax
The syntax for the above queue call is displayed below:

#include <fcntl.h>
/* used to open the files */
#include <sys/stat.h>
/* to determine a file based on the path */
#include <mqueue.h>
/* to include message queue descriptions */
mqd_t mq_open (const character *name, int oflag);
/* to open up and access the queue */
mqd_t mq_open (const character *name, int oflag, mode_t mode,
    struct mq_attribute *attribute);

Mq_Flags: Could be O or non-block

Mq_MaxMsg: Maximum number of messages that can be entered inside the queue

Mq_Msgsize: Maximum number of bytes in a message

Mq_CurMsgs: Currently sent messages within a queue

mq_close calls: To close all of the queue descriptors.

mq_notify

It is a call used to register and unregister arrival notification when a message enters an empty queue.

Syntax

#include <mqueue.h>
/* to include all of the message queue descriptions from the code */
int mq_notify (mqd_t mqdes, const struct sigevent *sevp);
/* to notify the arrival of the message in a queue */

mq_unlink

It is used to remove the queue having queue_name.

Syntax

int mq_unlink(const char *queue_name);
/* To remove the queue having name as queue_name */

mq_getattr, mq_setattr

This function has an attribute structure:

struct mq_attr is used as a message queue for descriptors.

mq_setattr is used for setting the attributes inside a queue.

Syntax

#include <mqueue.h>
int mq_getattribute(mqd_t mqdes, struct mq_attribute *attribute);
int mq_setattribute(mqd_t mqdes, const struct mq_attribute *newattribute,
    struct mq_attribute*oldattr);

Example: Client-Server Communication via POSIX

The following is an example of performing client-server communication via POSIX message queues. In the example, we will have a client file and server file.

We will have two files: the first (server) file is server.c, and the other (client) file is client.c.

Server Code

The image displayed below shows the code that we used for client-server communication. First, we called some libraries to define the strings, variables, and functions. Then, we defined the fcntl function and the name of the queue server. After that, we defined the name of the server queue, followed by its message size and buffer size, to define the size of messages to fit our buffer at a time. Next, we called and described the queues, then we generated the next tokens to see the client response once it was sent to the client. Finally, the confirmation was completed by printing the message from the server end. In the next section, you will see the flags discussed in the earlier section.

We initialized all flags, including mq_flags, mq_maxmsgs, etc. to proceed with storing requests. Then, we applied the condition to the name of the server and stored the messages in the queue buffer. After this, at the time of storage, we ensured that the queues followed a first-come-based priority rule. At the end, the code displays a failure message if there are any errors received from the client-end. Finally, we exited the server to send the request to the client.

Save the server.c file

Client Code

We will now discuss the second file. The image displayed below is the code we used for the client-server communication. The code began by calling standard libraries and defining variable headers. Then, we defined the strings and all types of data. After that, we declared the header of the queue to define the server queue name. Next, we defined the permission queues and message size inside the queue, along with the size of the message buffer (the maximum size that could fit inside the queue).

We will describe the queues and create a new client to receive the messages sent from the end of the server. Then, we will call the flags and initialize them, and call the client-end function. It will exit the function in the case of an error. The value is stored inside the buffer, and a request response is sent to the server. In case of a response, the server will then provide the token, which is printed once the client end has entered the input. In case of an error, it will return the error values, i.e., the client has not been able to send a message to the server. After that, we will exit the client.

Save the client.c file

Executing the Files

We are using a gcc compiler to execute the files. To run the server end file, type the appended command in the terminal window:

$ sudo gcc server.c -lrt

Next, type the following:

$ ./a.out

The output will appear as follows:

Moving on to the client response, type the following:

$ sudo gcc client.c -lrt

Then run the following:

$ ./a.out

The output will appear as follows:

Conclusion

In this article, you learned how to send POSIX Message Queues with C programming, as well as some of its functions. Then, you saw some examples of this process in greater detail.

About the author

Aqsa Yasin

I am a self-motivated information technology professional with a passion for writing. I am a technical writer and love to write for all Linux flavors and Windows.