Linux Environment Process Communication (3): Message Queue
content:
I. Basic concept of message queue II. Operation message queue three, message queue limit four, message queue application instance summary: Reference About the author
related information:
Communication between Linux Environment (1): Distance between pipelines and well-known pipes Linux Environment Processes (2): Signals (on) Linux Environment Processes Communication (2): Signals (below)
In the Linux area:
Tutorial Tools & Product Codes & Component Articles
Zheng Yanxing (mlinux@163.com) National Defense Science and Technology Pursue Ph.D. in January 2003
The first two parts of this series, we discuss
Pipeline and
Signal two communication mechanisms, this article will in depth, introduce the system V message queue and its corresponding API.
The message queue (also called a message queue) can overcome some shortcomings in the early UNIX communication mechanism. As a signal, one of the early UNIX communication mechanisms is limited, and later, although POSIX 1003.1B has been extended in terms of the real-time performance of the signal, the signal has a considerable degree of improvement in the amount of information, but the signal is The communication mode is more like "instant" communication, it requires the process to receive the signal to react with the signal within a certain time range, so the signal is more meaningful in the life cycle of the signal process, the information transmitted by the signal. It is close to Process-persistent, see Appendix 1; pipelines and well-known pipes and well-known pipes are typical to continuous IPC with process, and can only transfer unformatted byte streams will undoubtedly give the application. Development is inconvenient, in addition, its buffer size is also limited. The message queue is a message list. Messages can be viewed as a record, with specific formats and specific priorities. The process of writing permissions for the message queue can add new messages to the in-one rule; a process of read permissions to the message queue can read the message from the message queue. The message queue is in place with within, (see Appendix 1). There are currently two types of message queues: POSIX message queue and system V message queue, system V message queue is currently used in large use. Considering the portability of the program, the newly developed application should try to use the POSIX message queue. In this series of topics (deeply understood communication (IPC)), there are two implementation versions for message queues, signal lights, and shared memory regions. Posix and system v. Linux kernel (kernel 2.4.18) supports POSIX signal light, POSIX shared memory area, and POSIX message queues, but for one of the mainstream Linux release, REDHAD 8.0 (kernel 2.4.18), no support between POSIX processes communication API However, it should be just a matter of time. Therefore, this article will mainly introduce the system V message queue and its corresponding API. In the case where there is no declaration, the following discussion refers to the system V message queue. First, message queue basic concept
The system V message queue is continuous, and the message queue will be truly deleted with the kernel, and the message queue will be truly deleted. Therefore, the data structure (Struct IPC_IDS MSG_IDS) in the system (Struct IPC_IDS MSG_IDS) is located in the kernel, and all message queues in the system can find access inlets in the structure MSG_IDS. The message queue is a message list. Each message queue has a queue header with structural struct msg_queue (see Appendix 2). The queue head contains a large amount of information of the message queue, including the message queue key value, user ID, group ID, message queue number, etc., and even records the ID of the recently written process for the message queue. The reader can access this information or set some of these information. The following figure illustrates how the kernel and message queue establishes contact: where: struct ipc_ids msg_ids is the global data structure of logging messages in the kernel; struct msg_queue is a queue header of each message queue. As can be seen from the above figure, the global data structure Struct IPC_IDS MSG_IDS can access the first member of each message queue: struct kern_ipc_perm; and each struct kern_ipc_perm can correspond to the specific message queue because in this structure, There is a key_t type member Key, and Key uniquely determines a message queue. The Kern_iPC_Perm structure is as follows:
The global data structure MSG_IDS of the record message queue in the Struct Kern_iPC_Perm {// core can access the structure;
Key_t key; // This key value is unique to correspond to a message queue
UID_T UID;
GID_T GID;
UID_T CUID;
GID_T CGID;
Mode_t mode;
UNSIGNED Long SEQ;
}
Second, the operation message queue is nothing more than three types of messages in the message queue: 1. Open or create a message queue message queue's kernel perseverance requires that each message queue corresponds to a unique key value within the system, so to get A message queue describes the key value of the message queue; Note: Message queue descriptors are generated by the unique key value within the system, and the key value can be seen as a road within the corresponding system. through. 2, read and write operation messaging operation is very simple, for developers, each message is similar to the following data structure:
Struct msgbuf {
Long mtype;
Char mtext [1];
}
The MTYPE member represents a message type, an important basis for reading the message from the message queue is the type of message; MTEXT is the message content, of course, the length is not necessarily 1. Therefore, for the send message, first preset a MSGBUF buffer and write a message type and content, call the corresponding send function; for the reading message, first assign such an MSGBUF buffer, then read the message Enter the buffer. 3, gain or set the message queue properties: The message of the message queue is basically stored in the message team head, so a structure similar to the message queue head can be assigned (Struct MSQID_DS, see Appendix 2) to return the property of the message queue. This data structure can also be set.
Message queue API 1, file name to key value
#include
#include
Key_T FTOK (Char * Pathname, Char Proj);
It returns a key value corresponding to the path PathName. This function is not directly on the message queue, but the function is often called before calling IPC (Msgget, ...) or Msgget () to get the message queue descriptor. Typical call code is: key = ftok (path_ptr, 'a');
IPC_ID = IPC (msgget, (int) key, flags, 0, null, 0);
...
2, Linux provides a unified user interface for the three ways of communication between the operating system V process (message queue, signal light, shared memory area): int ipc (unsigned int call, int first, int special, int third, void * PTR, long fiffh; the first parameter indicates the operation of the IPC object, with four operations for the message queue: MSGSND, MSGRCV, MSGGET, and MSGCTL, send a message to the message queue, read the message from the message queue , Open or create a message queue, control the message queue; the first parameter represents the unique IPC object; the following will be introduced.
INT IPC (Msgget, Int First Second, INT THIRD, VOID * PTR, LONG FIFTH); system V call corresponding to this operation is: int msgget ((key_t) first, second). INT IPC (MSGCTL, INT Sec, INT Second, INT Third, Void * Ptr, Long Fiffh) The system V call corresponding to this operation is: int msgctl (first, second, (struct msqid_ds *) PTR). INT IPC (MSGSND, INT FIRST, INT Second, Int Third, Void * PTR, Long Fiffh); system V call corresponding to this operation is: int msgsnd (first, (struct msgbuf *) PTR, SECOND, THIRD). INT IPC (MSGRCV, INT First, INT Second, Int Third, Void * PTR, Long Fiffh); System V call corresponding to this operation is: int MSGRCV (First Msgbuf *) PTR, SECOND, FIFTH, THIRD) Note: I don't advocate the use of the system to call IPC (), and more inclined to use the system V or POSIX process to communicate API. The reason is as follows:
Although the system call provides a unified user interface, it is because of this feature, its parameter can hardly give specific practical significance (such as first, second to naming parameters), causing inconvenient development to a certain extent. As IPC manual saying: IPC () is unique to Linux. When writing a program, you should pay attention to the transplantability of the program; the implementation of the system call is not limited to the system V IPC function, and there is no efficiency; The number of APIs in the IPC is not much in the IPC, and the form is also simple. 3. System V Message Queue API System V Message Queue API has four, and you need to include several headers:
#include
#include
#include
1) INT MSGGET (key_t key, int msgflg) Parameter key is a key value, obtained by FTOK; MSGFLG parameters are some flag. This call returns a message queue descriptor that corresponds to a health check. In both cases, the call will create a new message queue: if there is no message queue corresponding to the valuable key, and the MSGFLG contains the IPC_CREAT flag; the key parameter is IPC_Private; the parameter MSGFLG can be below: IPC_CREAT, IPC_EXCL, IPC_NOWAIT or three or results. Call Return: Successfully Returns the message queue descriptor word, otherwise returns -1. Note: Parameter Key Set to constant IPC_Private does not mean that other processes cannot access the message queue, which means that new message queues are just now. 2) INT MSGRCV (INT MSQID, Struct Msgbuf * MSGP, INT MSGSZ, Long MSGTYP, INT MSGFLG); This system calls a message from the message queue represented by MSGID and stores the message in the MSGBUF structure pointed to by MSGP. MSQID describes the word queue; the message returns to the address pointed to by the MSGP, and the MSGSZ specifies the length of the MSGBUF's MTEXT member (ie, the length of the message content), the MSGTYP is the message type of the request read; the reading message flag MSGFLG can be the following Fast value:
IPC_NOWAIT If there is no message, the call is returned immediately. At this time, errno = enomsg IPC_EXCEPT is used in conjunction with msgtyp> 0, and the first type in the return queue is not for MSGTYP's message IPC_NoError If the message content that satisfies the condition in the queue is greater than the request The MSGSZ byte, cutting the message, and the cut-off section will be lost. During the MSGRCV manual, the message type is given to different values in detail (> 0; <0; = 0), which message will be returned to the message queue. Msgrcv () There are three conditions that relieve block:
The message queue has a message that satisfies the condition; the message queue represented by MSQID is deleted; the process that calls the msgrcv () is interrupted; the call returns: successfully returns the actual number of bytes of the read message, otherwise returns -1. 3) INT MSGSND (INT MSQID, Struct Msgbuf * MSGP, INT MSGSZ, INT MSGFLG); sending a message to the Message queue represented by Msgid, the message to be sent in the MSGBUF structure pointed to by the MSGP, specified by Msgze. For sending messages, meaningful MSGFLG flags are 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 types that cause msgsnd () waiting for:
The size of the current message is the sum of the number of bytes in the current message queue exceeds the total capacity of the message queue; the number of messages of the current message queue (unit "one") is not smaller than the total capacity of the message queue (unit "byte") At this time, although the number of messages in the message queue is a lot, only one byte is basically one byte. There are three in msgsnd () to release the block:
The above two conditions are not met, that is, the message queue is accommodated; the message queue represented by the MSQID is deleted; the process that calls the msgsnd () is interrupted by the signal; the call returns to 0, otherwise returns -1. 4) INT MSGCTL (INT MSQID, INT CMD, Struct MSQID_DS * BUF); This system call performs CMD operations for messages identified by MSQID, a total of three CMD operations: IPC_STAT, IPC_SET, IPC_rmid. IPC_STAT: This command is used to get the message queue information, and the returned information is stored in the MSQID structure pointed to by the BUF; IPC_set: This command is used to set the properties of the message queue, and the attribute to be set is stored in the MSQID structure pointed to by the BUF; Setting properties include: msg_perm.uid, msg_perm.gid, msg_perm.mode, and msg_qbytes, also affects MSG_ctime members. IPC_rmid: Delete the message queue of the MSQID identity; call back: successfully returns 0, otherwise returns -1. Third, the message queue limits the capacity of each message queue (the number of bytes that can accommodate) has a limit, which is different due to the system. In the following application example, the REDHAT 8.0 is output, and the results are taken in Appendix 3. Another limit is the maximum number of messages that each message queue can accommodate: In REDHAD 8.0, this limit is a message queue capacity: message number is less than the capacity of the message queue (byte). Note: The above two restrictions are for each message queue, and the system has a maximum number of messages within the system range, and the maximum number of messages over the system range. In general, this limit is not exceeded during the actual development process. Fourth, the message queue application instance message queue application is relatively simple, the following instance basically covers all the operations of the message queue, and the program output results help to deepen the understanding of certain rules and message queue restrictions on the previously described.
#include
#include
#include
Void msg_stat (int, struct msqid_ds);
Main ()
{
Int gflags, sflags, rflags;
Key_t key;
INT MSGID;
Int revAl;
Struct msgsbuf {
Int mType;
Char mtext [1];
} msg_sbuf;
Struct msgmbuf
{
Int mType;
Char mtext [10];
} msg_rbuf;
Struct msqid_ds msg_ginfo, msg_sinfo;
Char * msgpath = "/ unix / msgqueue";
Key = ftok (msgpath, 'a');
GFLAGS = IPC_CREAT | IPC_EXCL;
MSGID = msgget (key, gflags | 00666);
IF (MSGID == - 1)
{
Printf ("MSG Create Error / N);
Return;
}
// After creating a message queue, output the message queue default attribute
Msg_stat (msgid, msg_ginfo);
Sflags = IPC_NOWAIT;
Msg_sbuf.mtype = 10;
Msg_sbuf.mtext [0] = 'a';
Reval = msgsnd (msgid, & msg_sbuf, sizeof (msg_sbuf.mtext), sflags); if (Reval == - 1)
{
Printf ("Message Send Error / N");
}
// After sending a message, output message queue properties
Msg_stat (msgid, msg_ginfo);
RFLAGS = IPC_NOWAIT | MSG_NoError;
Reval = MSGRCV (MSGID, & MSG_RBUF, 4, 10, RFLAGS);
IF (Reval == - 1)
Printf ("Read Msg Error / N");
Else
Printf ("Read from Msg Queue% D Bytes / N", Reval;
// After reading the message from the message queue, output the message queue attribute
Msg_stat (msgid, msg_ginfo);
Msg_sinfo.msg_perm.uid = 8; // Just A Try
Msg_sinfo.msg_perm.gid = 8; //
Msg_sinfo.msg_qbytes = 16388;
// This verifies that the super user can change the default MSG_QBYTES of the message queue.
/ / Note The value set here is greater than the default value
Reval = msgctl (MSGID, IPC_SET, & MSG_SINFO);
IF (Reval == - 1)
{
Printf ("MSG SET INFO ERROR / N);
Return;
}
Msg_stat (msgid, msg_ginfo);
// Verify setting message queue properties
Reval = msgctl (MSGID, IPC_rmid, null); // Delete Message Queuing
IF (Reval == - 1)
{
Printf ("Unlink Msg Queue Error / N");
Return;
}
}
Void MSG_Stat (int msgid, struct msqid_ds msg_info)
{
Int revAl;
Sleep (1); // is just convenient for the back output time
Reval = msgctl (MSGID, IPC_STAT, & MSG_INFO);
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 of each message queue (byte) has restricted MSGMNB, and the value of the value varies depending on the system. When you create a new message queue, // msg_qbytes default is MSGMNB
Printf ("PID of Last MSGSND IS% D / N", MSG_INFO.MSG_LSPID);
Printf ("PID of Last MSGRCV IS% D / N", MSG_INFO.MSG_LRPID);
Printf ("Last Msgsnd Time IS% S", CTIME (& (MSG_INFO.MSG_STIME))));
Printf ("Last Msgrcv Time IS% S", CTIME (& (MSG_INFO.MSG_RTIME))); Printf ("Last Change Time IS% S", CTIME (& (MSG_INFO.MSG_CTIME));
Printf ("MSG UID IS% D / N", MSG_INFO.MSG_PERM.UID);
Printf ("MSG GID IS% D / N", MSG_INFO.MSG_PERM.GID);
}
Program output results See Appendix 3. Summary: Message queue compared to pipelines and well-known pipes, which is more flexible. First, it provides formatted word current, which is conducive to reducing the workload of developers; secondly, messages have type, in practical applications, As a priority. These two points are not comparable to the pipeline and a famous pipe. Similarly, the message queue can be multiplexed between several processes, regardless of whether these processes have a relaxation relationship, this is very similar to the famous pipeline; but the message queue is in place, with the famous pipe (continued) Comparison, more vitality is stronger and the application is larger. Appendix 1: In Reference [1], IPC has been given to the process continued, and the continued definition of kernel and file system:
Continued with the process: IPC has always exists to turn off the object until the last process of opening an IPC object. Such as pipelines and well-known pipes; continued with the kernel: IPC continues until the kernel re-boost or display the object. Such as message queues, signal lights, shared memory, etc .; continued with the file system: IPC continues until the object is displayed. Appendix 2: Structure MSG_QUEUE is used to describe the header header, exist in system space:
Struct MSG_QUEUE {
Struct Kern_iPC_Perm Q_Perm;
Time_t q_stime; / * Last Msgsnd Time * /
Time_t q_rtime; / * Last Msgrcv Time * /
Time_t q_ctime; / * last change time * /
Unsigned long Q_cBytes; / * Current Number of bytes on queue * /
Unsigned long Q_Qnum; / * Number of Messages in queue * /
Unsigned long Q_QBytes; / * max number of bytes on queue * /
PID_T Q_LSPID; / * PID of Last Msgsnd * /
PID_T Q_LRPID; / * Last Receive PID * /
Struct List_Head Q_Messages;
Struct List_Head Q_RecEivers;
Struct List_Head Q_Senders;
}
Structure MSQID_DS is used to set or return information of message queue, exist in user space;
Struct msqid_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 32 bit * /
Unsigned long msg_lqbytes; / * ditto * /
Unsigned short msg_cBytes; / * current number of bytes on queue * /
Unsigned short msg_qnum; / * Number of Messages in queue * /
Unsigned short msg_qbytes; / * max number of bytes on queue * /
__kernel_ipc_pid_t msg_lspid; / * Pid of last msgsnd * /
__kernel_ipc_pid_t msg_lrpid; / * Last Receive Pid * /
}
// It can be seen that the above two structures are similar. Appendix 3: Message Queue Instance Output Result:
Current Number of Bytes on Queue IS 0
Number of Messages in Queue Is 0
Max number of bytes on queue is 16384
PID of last msgsnd is 0
Pid of last MSGRCV IS 0
Last Msgsnd Time Is Thu Jan 1 08:00:00 1970
Last Msgrcv Time Is Thu Jan 1 08:00:00 1970
Last Change Time Is Sun Dec 29:28:20 2002
MSG Uid IS 0
MSG GID IS 0
/ / The output just created on a new message queue
Current Number of Bytes on Queue IS 1
Number of Messages in Queue IS 1
Max number of bytes on queue is 16384
Pid of last msgsnd is 2510
Pid of last MSGRCV IS 0
Last Msgsnd Time IS Sun Dec 29 18:28:21 2002
Last Msgrcv Time Is Thu Jan 1 08:00:00 1970
Last Change Time Is Sun Dec 29:28:20 2002
MSG Uid IS 0
MSG GID IS 0
Read from msg queue 1 bytes
/ / Actually read the number of bytes
Current Number of Bytes on Queue IS 0
Number of Messages in Queue Is 0
Max number of bytes on queue is 16384 // Each message queue maximum capacity (byte)
Pid of last msgsnd is 2510
Pid of last MSGRCV IS 2510
Last Msgsnd Time IS Sun Dec 29 18:28:21 2002
Last Msgrcv Time Is Sun Dec 29:28:22 2002
Last Change Time Is Sun Dec 29:28:20 2002
MSG Uid IS 0
MSG GID IS 0
Current Number of Bytes on Queue IS 0
Number of Messages in Queue Is 0
Max number of bytes on queue is 16388 // can see superusers can modify message queue maximum capacity Pid of last msgsnd is 2510
PID of last MSGRCV IS 2510 // Tracking of the operating message queue process
Last Msgsnd Time IS Sun Dec 29 18:28:21 2002
Last Msgrcv Time Is Sun Dec 29:28:22 2002
Last Change Time Is Sun Dec 29 18:28:23 2002 // msgctl () invoking MSG_CTIME has an impact
MSG Uid IS 8
MSG GID IS 8
references:
UNIX Network Programming Volume II: inter-process communication, Author: W.Richard Stevens, translator: Yang Ji Zhang, Tsinghua University Press. Both POSIX and system v messages are elaborated, and there is a great inspiration for program development in the Linux environment. Linux kernel source code scenario analysis (on), Maunde, Hu Ximing, Zhejiang University Press, gives the source code analysis of the system V message queue. http://www.fanqiang.com/a4/b2/20010508/113315.html, mainly explained the operation of the file under Linux, detail the access rights of the file, which is also very good. Good reference significance. Msgget, MSGSND, MSGRCV, MSGCTL manual
About the author: Zheng Yanxing, National Defense Science and PhD. Contact: mlinux@163.com