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:
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:
/* 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
/* 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
/* 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
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:
Next, type the following:
The output will appear as follows:
Moving on to the client response, type the following:
Then run the following:
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.