I. Concepts
A message queue is a linked list of messages. A process with write permission on a message queue can add new messages to it according to certain rules. A process with read permission on the Message Queue can read messages from the message queue. Message Queues continue with the kernel. The following three concepts are introduced:
1. Continuous with process: IPC always exists until the last process that opens the IPC object closes the object, such as an MPS queue and a named MPs queue.
2; as the kernel continues: IPC continues until the kernel reboots or displays the deleted object. Such as message queue, semaphore, and shared memory
3; as the file system continues: IPC keeps displaying and deleting this object
System V message queue is widely used.
Ii. Message Queue Information
Each message queue has a queue header, which is described by the structure struct msg_queue. The queue header contains a large amount of information about the message queue, including the key value, user ID, group ID, and number of messages in the message queue, the ID of the read/write process of the message queue. You can access this information or set some information. This structure is stored in system space.
struct msg_queue { structkern_ipc_perm q_perm; time_tq_stime; /* last msgsndtime */ time_tq_rtime; /* last msgrcvtime */ time_tq_ctime; /* last changetime */ unsignedlong q_cbytes; /* current number of bytes on queue*/ unsignedlong q_qnum; /* number of messages inqueue */ unsignedlong q_qbytes; /* max number of bytes on queue */ pid_tq_lspid; /* pid oflast msgsnd */ pid_tq_lrpid; /* lastreceive pid */ structlist_head q_messages; structlist_head q_receivers; structlist_head q_senders;};
The structure msqid_ds is used to set or return message queue information, which exists in the user space;
structmsqid_ds{ struct ipc_perm msg_perm; struct msg *msg_first; /* first message on queue,unused*/ struct msg *msg_last; /* last message in queue,unused*/ __kernel_time_t msg_stime; /* last msgsnd time */ __kernel_time_t msg_rtime; /* last msgrcv time */ __kernel_time_t msg_ctime; /* last change time */ unsigned long msg_lcbytes; /* Reuse junk fields for 32bit */ unsigned long msg_lqbytes; /* ditto */ unsigned short msg_cbytes; /* current number of byteson queue */ unsigned short msg_qnum; /* number of messages in queue*/ unsigned short msg_qbytes; /* max number of bytes onqueue */ __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */ __kernel_ipc_pid_t msg_lrpid; /* last receive pid*/ };
3. Open and create a message queue
The kernel persistence of Message Queue requires that each Message Queue corresponds to a unique key value within the system range. Therefore, you must obtain a Message Queue description, you only need to provide the key value of the message queue. Msgget is used to create a message queue or open an existing queue.
Name :: |
Msgget |
Function: |
Create a Message Queue |
Header file: |
# Include <sys/types. h> # Include <sys/msg. h> # Inlcude <sys/IPC. h> |
Original function: |
Int msgget (key_t key, int msgflag ); |
Parameters: |
Key: the Key of the message queue. Flag flag Flag |
Return Value: |
If the message queue is successful, it is the message queue description. If an error occurs, it is-1. |
The parameter key is a key value obtained by ftok, And the msgflg parameter is a flag. This call returns the Message Queue description corresponding to the key.
In either of the following cases, this call creates a new message queue:
1. If no message queue corresponds to the key, and msgflg contains the ipc_creat flag;
2. The key parameter is ipc_private;
The msgflg parameter can be set to the following: ipc_creat (create Message Queue), ipc_excl (), ipc_nowait (), or the following values or results.
Note that when creating a new queue, the system automatically initializes the following members of the struct msqid_ds structure.
The ipc_perm structure is initialized as we mentioned previously. In this structure, the mode member is set according to the corresponding permission bit in the flag.
Msg_qnum, msg_lspid, msg_lrpid, msg_stime, and msg_rtime are all set to 0.
Msg_ctime is set to the current time.
Msg_qbytes is set as the system limit value.
4. Obtain and modify Message Queue attributes and delete message queues
Name :: |
Msgctl |
Function: |
Perform multiple operations on message queues |
Header file: |
# Include <sys/msg. h> |
Original function: |
Int msgctl (INT msqid, int cmd, struct msqid_ds * BUF ); |
Parameters: |
Msqid Message Queue description The operation to be performed by CMD. Buf the struct msqid_ds structure of this queue |
Return Value: |
If 0 is returned successfully,-1 is returned if an error occurs. |
The system calls the CMD operation on the message queue identified by msqid. There are three kinds of CMD operations: ipc_stat, ipc_set, and ipc_rmid.
Ipc_stat: this command is used to obtain Message Queue information. The returned information is stored in the msqid_da structure pointed to by the Buf;
Ipc_set: this command is used to set the attributes of a message queue. The attributes to be set are stored in the msqid_ds structure pointed to by the Buf. The attributes include msg_perm.uid, msg_perm.gid, msg_perm.mode, and msg_qbytes, it also affects msg_ctime members.
Ipc_rmid: Delete the Message Queue identified by msqid_ds.
5. send and receive messages in a message queue
Name :: |
Msgsnd |
Function: |
Put data on the message queue |
Header file: |
# Include <sys/types. h> # Include <sys/msg. h> # Inlcude <sys/IPC. h> |
Original function: |
Int msgsnd (INT msqid, struct msgbuf * msgp, int msgsz, int msgflg ); |
Parameters: |
Msqid Message Queue description Msgp pointer to message data Size of message sent by msgsz Msgflg flag |
Return Value: |
If the request is successful, it is 0. If the request fails, it is-1. |
Send a message to the Message Queue represented by msgid. The message to be sent is stored in the msgbuf structure pointed to by msgp. The message size is specified by msgze.
Structmsgbuf {
Longmtype;/* Message Type */
Charmtext [1];/* message data */
};
We can regard the msgbuf structure as a template. programmers can design a direct message structure based on their own needs. For example, if an application needs to exchange messages consisting of an integer followed by an 8-byte array, it can define its own structure as follows:
Typedefstruct my_msgbuf {
Longmtypel
Int mshort;
Char mchar [my_data];
} Message;
For sending a message, the meaningful msgflg flag is ipc_nowait, indicating whether msgsnd waits when the message queue does not have enough space to accommodate the message to be sent. There are two conditions that cause msgsnd () wait:
1. The sum of the current message size and the number of bytes in the current Message Queue exceeds the total capacity of the message queue;
2. the number of messages (in bytes) in the current message queue is no less than the total capacity (in bytes) of the Message Queue. At this time, although the number of messages in the message queue is large, however, there is only one byte.
There are three conditions for msgsnd () to remove blocking:
1. The above two conditions are not met, that is, there is space in the message queue to accommodate the message;
2. The message queue represented by msqid is deleted;
3. The process that calls msgsnd () is interrupted by the signal;
When msgsnd is returned successfully, the msqid_ds structure related to the message queue is updated to indicate the ID of the called process (msg_lspid) and the time (msg_stime) for the call ), and indicates that a message is added to the queue.
Vi. Use of Message Queue
# Include <sys/types. h> # include <sys/IPC. h> # include <sys/MSG. h> # include <unistd. h> void msg_stat (INT, struct msqid_ds); int main (void) {int gflags, sflags, rflags; key_t key; int msgid; int reval; struct msgsbuf {int mtype; char mtext [1];} msg_sbuf;/* message sending buffer Data Structure */struct msgmbuf {int mtype; char mtext [10];} msg_rbuf; /* receive message buffer Data Structure */struct msqid_ds msg_ginfo, msg_sinfo; char * msgpath = "/Unix/msgqueue"; Key = ftok (Msgpath, 'A');/* Get the key value of the Message Queue */gflags = ipc_creat | ipc_excl; msgid = msgget (Key, gflags | 00666 ); /* Call msgget to create a message queue */If (msgid =-1) {printf ("MSG create error \ n"); return;} msg_stat (msgid, msg_ginfo ); /* after a message queue is created, the default attribute of the Output Message Queue is displayed. The first call of the msg_stat subfunction */sflags = ipc_nowait;/* when the message queue is full, msgsnd does not wait and an error is returned immediately */msg_sbuf.mtype = 10; msg_sbuf.mtext [0] = 'A '; /* message data to be sent */reval = msgsnd (msgid, & msg_sbuf, sizeof (msg_sbuf.mtext), sflags ); /* Call msgsnd to send a message */If (reval =-1) {printf ("Message send error \ n");} msg_stat (msgid, msg_ginfo ); /* after a message is successfully sent, the Message Queue attribute is output. The second call to the msg_stat subfunction */rflags = ipc_nowait | msg_noerror;/* For the meaning, see Table 10.1 */reval = msgrcv (msgid, & msg_rbuf, rflags ); /* Call msgrcv to receive the message. The length of the received data is 4, type> 0. The meaning is shown in Table 10.2 */If (reval =-1) {printf ("read MSG error \ n");} else {printf ("read from MSG queue % d bytes \ n", Reval ); /* print the number of bytes of received data */} msg_stat (msgid, msg_ginfo);/* output the Message Queue attributes again after reading the message from the message queue. The third call to the msg_stat subfunction */msg_sinfo.msg_perm.uid = 8;/* tries to change the default attribute of the Message Queue (root user permission is required), and the owner's valid user ID is changed to 8 */msg_sinfo.msg_perm.gid; /* the owner's valid group ID of the message queue is changed to 8 */msg_sinfo.msg_qbytes = 16388;/* the maximum number of bytes allowed by the message queue is changed to 16388 (default: 16384) */reval = msgctl (msgid, ipc_set, & msg_sinfo);/* Call msgctl to set Message Queue attributes */If (reval =-1) {printf ("MSG set info error \ n"); return;} msg_stat (msgid, msg_ginfo);/* sets the Message Queue attribute. The third call to the msg_stat subfunction */reval = msgctl (msgid, ipc_rmid, null);/* after the operation is completed, call msgctl to delete the Message Queue */If (reval =-1) {printf ("unlink MSG queue error \ n"); return;} return 0;} void msg_stat (INT msgid, struct msqid_ds msg_info) {int reval; sleep (1 ); /* only for the convenience of subsequent output time */reval = msgctl (msgid, ipc_stat, & msg_info ); /* Call msgctl to obtain Message Queue attributes */If (reval =-1) {printf ("Get MSG info error \ n"); return ;} printf ("\ n"); printf ("current number of bytes on Queue is % d \ n ", msg_info.msg_cbytes); printf (" number of messages in queue is % d \ n ", msg_info.msg_qnum ); printf ("Max number of bytes on queue is % d \ n", msg_info.msg_qbytes);/* the capacity (number of bytes) of each message queue is limited to msgmnb, the value size varies with the system. When creating * // * a new message queue, the default value of msg_qbytes is msgmnb */printf ("PID of last msgsnd is % d \ n", msg_info.msg_lspid ); /* the ID of the last process that executes the msgsnd function */printf ("PID of last msgrcv is % d \ n", msg_info.msg_lrpid ); /* the ID of the last process that executes the msgrcv function */printf ("Last msgsnd time is % s", ctime (& (msg_info.msg_stime ))); /* The Last Time msgsnd was executed. Ctime () converts the time into the form of * // * for weeks, months, days, hours, and seconds, and years. It is a standard C function */printf ("Last msgrcv time is % s ", ctime (& (msg_info.msg_rtime);/* The Last Time msgrcv was executed */printf ("last change time is % s", ctime (& (msg_info.msg_ctime ))); /* the last time the message queue was changed */printf ("MSG uid is % d \ n", msg_info.msg_perm.uid ); /* valid user ID of the Message Queue owner */printf ("msg gid is % d \ n", msg_info.msg_perm.gid);/* Valid group ID of the Message Queue owner */}