Linux inter-process communication (IPC) Programming Practice (iii) Details System V Message Queue (1)
Message Queue introduction Message Queue provides a method for sending a piece of data (local) from one process to another. Each data block is considered to be of a type, the data blocks received by the recipient process can have different types of values. Message queues have the same limitations as pipelines:
(1) Maximum number of bytes per message (MSGMAX );
(2) the total number of message queues in the system also has an upper limit (MSGMNI );
(3) The total number of bytes that each Message Queue can store is limited (MSGMNB ).
The difference between message queue and MPs queue: The main difference is that the communication between MPs queue requires that the two processes have a kinship and can only carry the non-Format byte stream, two processes that communicate with each other can be completely unrelated. They are formatted (similar to TCP or UDP ). As for its difference from the famous Pipeline, first of all, FIFO is a communication method to be stored on the disk, while message queue is in the memory.
View the upper limit of the three limits in the system:
IPC Object Data Structure
// The kernel maintains a data structure struct ipc_perm {key_t _ key for each IPC object;/* Key supplied to msgget (2) */uid_t uid; /* Valid UID of owner */gid_t gid;/* Valid tive GID of owner */uid_t cuid;/* Valid valid UID of creator */gid_t cgid; /* Valid tive GID of creator */unsigned short mode;/* Permissions */unsigned short _ seq;/* Sequence number */};
// Message queue-specific structure struct msqid_ds {struct ipc_perm msg_perm;/* Ownership and permissions the data structures common to various IPC objects */time_t msg_stime; /* Time of last msgsnd (2) */time_t msg_rtime;/* Time of last msgrcv (2) */time_t msg_ctime; /* Time of last change */unsigned long _ msg_cbytes;/* Current number of bytes in queue (nonstandard) the number of bytes currently saved in the message queue */msgqnum_t msg_qnum; /* Current number of messages in queue the number of currently stored messages in the message queue */msglen_t msg_qbytes; /* Maximum number of bytes allowed by Maximum number of bytes allowed in queue Message queue */pid_t msg_lspid;/* PID of last msgsnd (2) the last process number that sends data */pid_t msg_lrpid;/* PID of last msgrcv (2) the last accepted process Number */};
Message Queue representation in the kernel
Messages are organized as linked lists in message queues. The types of each node are similar to the following:
Struct msq_Node {Type msq_type; // Type Length msg_len; // Length Data msg_data; // Data struct msg_Node * next ;};
Basic API of Message Queue
#include
#include
#include
int msgget(key_t key, int msgflg); int msgctl(int msqid, int cmd, struct msqid_ds *buf); int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
This section describes the first two APIs. For more information about the APIs for sending and receiving messages, see the next blog.
Msgget
int msgget(key_t key, int msgflg);
Parameters:
Key: The name of a message queue.
Msgflg: consists of nine permission tags, such as 0644. Their usage is the same as the mode flag used when creating a file (but the message queue does not have the x (execution) Permission)
Return Value:
A Message Queue ID is returned, that is, the ID code of the message queue.
Next, let's take a few examples to see the different operations and results of creating a message queue:
/** Example 1: Specify IPC_CREAT at msgflg. If this message queue does not exist, create **/int main (int argc, char * argv []). {// specify IPC_CREAT. if it does not exist, create the Message Queue int msgid = msgget (1234,066 6 | IPC_CREAT); if (msgid =-1) err_exit ("msgget error "); cout <"msgget success" <endl ;}
Note:The KEY is displayed in hexadecimal notation. You can use the command ipcrm-q to delete a message queue or ipcrm-Q [key] (key! = 0); Ipcs to view message queues; IPC_CREAT must be specified before creation, similar to the creat of a file
/** Example 2: IPC_CREAT | IPC_EXCL. If the Message Queue already exists, an error is returned. **/int main (int argc, char * argv []) {// specify IPC_EXCL. if yes, the report file already exists (error) int msgid = msgget (1234,066 6 | IPC_CREAT | IPC_EXCL); if (msgid =-1) err_exit ("msgget error"); cout <"msgget success" <endl ;}
/** Example 3: specify the key as IPC_PRIVATE (value: 0) and then specify the key as IPC_PRIVATE, msgget creates a new message queue each time it is called, and the descriptors of the created message queue are different! Therefore, unless MessageID (key) is sent to another process (unless there is an associated process ), otherwise, other processes cannot use this message queue, but those with kinship processes can be used (fork). Therefore, the Message Queue created by IPC_PRIVATE can only be used in processes related to the current process! **/This also means that the process cannot share the message queue. The Parent and Child sibling processes can use int main (int argc, char * argv []). {// specify IPC_PRIVATE int msgid = msgget (IPC_PRIVATE, 0666 | IPC_CREAT | IPC_EXCL); if (msgid =-1) err_exit ("msgget error "); cout <"msgget success" <endl ;}
All the above keys with 0x00000000 are created using IPC_PRIVATE.
/** Example 4: When only the message queue is enabled, the msgflg option can be ignored directly (enter 0 ), in this case, the **/int main (int argc, char * argv []) {int msgid = msgget (1234, 0) is enabled Based on the permission when a message queue is created ); if (msgid =-1) err_exit ("msgget error"); cout <"msgget success" <endl; cout <"msgid =" <msgid <endl ;}
// Example 5: Create with low permissions and enable int main () {// create int msgid = msgget (0x255, 0444 | IPC_CREAT) with high permissions; if (msgid <0) err_exit ("mesget error"); else cout <"Create Mes OK, msgid =" <msgid <endl; // enable msgid = msgget (0x255,0644 | IPC_CREAT) with high permissions; if (msgid <0) err_exit ("mesget error"); else cout <"Create Mes OK, msgid = "<msgid <endl ;}
"Permission denied" error will occur.
Msgctl Function
Function: gets/sets Message Queue information.
[Cpp]View plaincopy
- Int msgctl (int msqid, int cmd, struct msqid_ds * buf );
Parameters:
Msqid: ID of the Message Queue returned by the msgget Function
/** Example 1: IPC_RMID. delete a message queue. Note: The Message Queue does not use the reference count function. **/int main () {int msgid = msgget (1234, 0); if (msgid =-1) err_exit ("msgget error"); if (msgctl (msgid, IPC_RMID, NULL) =-1) err_exit ("msgctl IPC_RMID error"); cout <"msgctl IPC_RMID success" <endl ;}
/** Example 2: IPC_STAT. Message Queue-related information is read into buf **/int main () {int msgid = msgget (0x255,066 6 | IPC_CREAT ); if (msgid =-1) err_exit ("msgget error"); struct msqid_ds buf; if (msgctl (msgid, IPC_STAT, & buf) =-1) err_exit ("msgctl error"); printf ("buf. msg_perm.mode = % o \ n ", buf. msg_perm.mode); // % o print printf ("buf. _ key = % x \ n ", buf. msg_perm. _ key); // % x prints cout in hexadecimal format <"buf. _ msg_cbytes = "<buf. _ msg_cbytes <endl; cout <"buf. msg_qbytes = "<buf. msg_qbytes <endl; cout <"buf. msg_lspid = "<buf. msg_lspid <endl ;}
** Practice: IPC_SET, which is usually obtained first, and then set **/int main () {int msgid = msgget (0x255, 0 ); if (msgid =-1) err_exit ("msgget error"); // get the message queue attributes struct msqid_ds buf; if (msgctl (msgid, IPC_STAT, & buf) =-1) err_exit ("msgctl error"); // set the attribute buf of the message queue. msg_perm.mode = 0600; if (msgctl (msgid, IPC_SET, & buf) =-1) err_exit ("msgctl error"); // get and print bzero (& buf, sizeof (buf); if (msgctl (msgid, IPC_STAT, & buf) =-1) err_exit ("msgctl IPC_STAT error "); printf ("mode = % o \ n", buf. msg_perm.mode );}