I. I have introduced the knowledge about System V message queues. Now let's take a look at POSIX message queues.
In fact, message queue is a place where data can be exchanged between processes. The biggest difference between the two standard message queues may be the differences between API functions. For example, the System V series of functions are msgxxx, POSIX is mq_xxx. POSIX message queue also has some restrictions on message length, such as man 7 mq_overview:
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $ CAT/proc/sys/fs/mqueue/msg_max
10
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $ CAT/proc/sys/fs/mqueue/msgsize_max
8192
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $ CAT/proc/sys/fs/mqueue/queues_max
256
That is to say, a message queue can have up to 10 messages, each of which has a maximum length of 8192 bytes, and a system can have up to 256 message queues.
Another point is that in Linux, POSIX message queue is implemented by a virtual file system and must be mounted to a directory to see it, as shown in
# Mkdir/dev/mqueue
# Mount-T mqueue NONE/dev/mqueue
Run the cat command to view the status of the Message Queue. Assume that mymq is the name of the created message queue.
$ CAT/dev/mqueue/mymq
Qsize: 129 notify: 2 signo: 0 notify_pid: 8260
Qsize: The data length of all messages in the message queue.
Policy_pid: A process uses mq_policy to register a message to an asynchronous notification event, that is, the PID of the process.
Y: notification method: 0 is sigev_signal; 1 is sigev_none; and 2 is sigev_thread.
Signo: indicates the signal number when it is notified by signal.
Ii. Series functions. Add the-LRT option during compilation to connect to the Library (Real-time library)
# Include <fcntl. h>/* For o _ * constants */
# Include <sys/STAT. h>/* for mode constants */
# Include <mqueue. h>
Function: Creates and accesses a message queue.
Prototype
Mqd_t mq_open (const char * Name, int Oflag );
Mqd_t mq_open (const char * Name, int Oflag, mode_t mode, struct mq_attr * ATTR );
Parameters
Name: The name of a message queue. It must start with "/" and cannot contain other "/" in the future. For example, the length of "/somename" cannot exceed name_max (255)
Oflag: similar to open functions, it can be o_rdonly, o_wronly, o_rdwr, or o_creat, o_excl, or o_nonblock;
Mode: If Oflag specifies o_creat, you need to set the mode.
Returned value: the message queue file descriptor is returned successfully;-1 is returned if the message queue file descriptor fails to be returned.
Function: Disable message queue.
Prototype
Mqd_t mq_close (mqd_t mqdes );
Parameters
Mqdes: Message Queue Descriptor
Return Value: 0 is returned for success;-1 is returned for failure.
Function: deletes a message queue.
Prototype
Mqd_t mq_unlink (const char * Name );
Parameters
Name: name of the Message Queue
Return Value: 0 is returned for success;-1 is returned for failure.
Function: Get/Set message queue attributes
Prototype
Mqd_t mq_getattr (mqd_t mqdes, struct mq_attr * ATTR );
Mqd_t mq_setattr (mqd_t mqdes, struct mq_attr * newattr, struct mq_attr * oldattr );
Return Value: 0 is returned for success;-1 is returned for failure.
Struct mq_attr {
Long mq_flags;/* flags: 0 or o_nonblock */
Long mq_maxmsg;/* max. # of messages on queue */
Long mq_msgsize;/* max. Message Size (bytes )*/
Long mq_curmsgs;/* # of messages currently in queue */
};
Mq_flags indicates the maximum number of messages in a message queue. mq_maxmsg indicates the maximum number of messages in a message queue. mq_msgsize indicates the maximum number of messages in a message queue. mq_curmsgs indicates the current number of messages.
Function: send messages.
Prototype
Mqd_t mq_send (mqd_t mqdes, const char * msg_ptr, size_t msg_len, unsigned msg_prio );
Parameters
Mqdes: Message Queue Descriptor
Msg_ptr: pointer to the message
Msg_len: message length
Msg_prio: Message priority
Return Value: 0 is returned for success;-1 is returned for failure.
Function: receives messages.
Prototype
Ssize_t mq_receive (mqd_t mqdes, char * msg_ptr, size_t msg_len, unsigned * msg_prio );
Parameters
Mqdes: Message Queue Descriptor
Msg_ptr: returns the received message.
Msg_len: message length, which must be specified as msgsize_max.
Msg_prio: return the priority of the received message
Returned value: the number of received message bytes is returned successfully;-1 is returned if a message fails to be returned.
Note: return the earliest message with the highest priority in the specified message queue. The lowest priority is 0.
Function: Creates or deletes a message Arrival notification event.
Prototype
Mqd_t mq_notify (mqd_t mqdes, const struct sigevent * notification );
Parameters
Mqdes: Message Queue Descriptor
Notification:
Non-null indicates that when a message arrives and the message queue is empty, the message will be notified;
Null indicates canceling registered notifications.
Return Value: 0 is returned for success;-1 is returned for failure.
Notification method:
Generate a signal
Creates a thread to execute a specified function.
Union sigval {/* data passed with notification */
Int sival_int;/* integer value */
Void * sival_ptr;/* pointer value */
};
Struct sigevent {
Int
Sigev_notify;/* Notification Method */
Int
Sigev_signo;/* notification signal */
Union sigval
Sigev_value;/* data passed with notification */
Void (* sigev_policy_function) (Union sigval );
/* Function for thread notification */
Void * sigev_policy_attributes;
/* Thread function attributes */
};
There are three values for sigev_notify:
Sigev_none: no notification will be sent when a message arrives.
Sigev_signal: sends a notification as a signal. When this option is set, sigev_signo sets the signal number and can only use sigev_value to carry data when the signal is a real-time signal.
Sigev_thread: notification by thread. When this option is set, sigev_policy_function is a function pointer. sigev_policy_attributes is the thread attribute.
Notes for mq_notify functions:
1. Only one process can be registered at any time to receive notifications from a given queue.
2. When a message arrives in a previously empty queue and a process is registered to receive notifications from the queue, the notification is sent only when no thread is blocked by the mq_receive call of the queue.
3. When a notification is sent to its registration process, its registration is revoked. The process must call mq_notify again to re-register the message (if necessary). re-register the message before and after reading the message from the message queue.
Below are two small programs to test:
Mq_send.c
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
# Include <stdio. h> # Include <stdlib. h> # Include <sys/IPC. h> # Include <sys/msg. h> # Include <sys/types. h> # Include <unistd. h> # Include <errno. h> # Include <mqueue. h> # Include <fcntl. h> # Include <sys/STAT. h> # Include <string. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) Typedef struct Stu { Char name [32]; Int age; } Stu; Int main (INT argc, char * argv []) { If (argc! = 2) { Fprintf (stderr, "Usage: % S <PRIO> \ n", argv [0]); Exit (exit_failure ); } Mqd_t mqid; Mqid = mq_open ("/ABC", o_wronly ); If (mqid = (mqd_t)-1) Err_exit ("mq_open "); Printf ("mq_open succ \ n "); Stu; Strcpy (STU. Name, "test "); Stu. Age = 20; Unsigned int PRIO = atoi (argv [1]); Mq_send (mqid, (const char *) & Stu, sizeof (Stu), PRIO ); Mq_close (mqid ); Return 0; } |
Mq_policy.c
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
|
# Include <stdio. h> # Include <stdlib. h> # Include <sys/IPC. h> # Include <sys/msg. h> # Include <sys/types. h> # Include <unistd. h> # Include <errno. h> # Include <mqueue. h> # Include <fcntl. h> # Include <sys/STAT. h> # Include <string. h> # Include <signal. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) Typedef struct Stu { Char name [32]; Int age; } Stu; Size_t size; Mqd_t mqid; Struct sigevent sigev; Void handle (INT sig) { Mq_policy (mqid, & sigev ); Stu; Unsigned int PRIO; Mq_receive (mqid, (char *) & Stu, size, & PRIO ); Printf ("name = % s, age = % d, PRIO = % d \ n", Stu. Name, Stu. Age, PRIO ); } Int main (INT argc, char * argv []) { Mqid = mq_open ("/ABC", o_rdonly ); If (mqid = (mqd_t)-1) Err_exit ("mq_open "); Printf ("mq_open succ \ n "); Struct mq_attr ATTR; Mq_getattr (mqid, & ATTR ); Size = ATTR. mq_msgsize; Signal (SIGUSR1, handle ); Sigev. sigev_notify = sigev_signal; Sigev. sigev_signo = SIGUSR1; Mq_policy (mqid, & sigev ); For (;;) Pause (); Mq_close (mqid ); Return 0; } |
Assume that a message queue has been created with mq_open and mounted to/dev/mqueue. You can view the status:
Simba @ Ubuntu:/dev/mqueue $ CAT/dev/mqueue/ABC
Qsize: 0 notify: 0 signo: 0 notify_pid: 0
Run./mq_policy and check the status:
Simba @ Ubuntu:/dev/mqueue $ CAT/dev/mqueue/ABC
Qsize: 0 notify: 0 signo: 10 notify_pid: 3572
The signal for preparing the notification is the 10th, namely SIGUSR1, and the waiting process PID is. /mq_policy. the/mq_notify process is blocked and is waiting for other processes to write messages to the Message Queue. It is running now. /mq_send
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $./mq_send
Usage:./mq_send <PRIO>
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $./mq_send 1
Mq_open succ
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $./mq_send 1
Mq_open succ
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $
Looking back at the output of./mq_notify:
Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/POSIX $./mq_policy
Mq_open succ
Name = test, age = 20, PRIO = 1
Name = test, age = 20, PRIO = 1
...........................................
That is. the two messages sent by/mq_send are received. Note that although the notification is one-time, we have registered the notification again in the message processing function, so we can receive the notification multiple times, however, the notification only occurs when the message queue is from empty to empty, if it runs first. /mq_send: If n messages are sent to the Message Queue first, execute. /mq_notify does not receive notifications and is blocked.