I recently debugged the Qt and DVR programs on Hi3515 and found that they use message queues for communication. In my spare time, I summarized the message queues, the strength of message queue is also found in the application.
AboutThread Management (mutex and condition variable)See:Essential for Linux thread management: Explanation of mutex resolution and conditional variables
I. Features of Message Queue
1. A message queue is a linked list of messages in a specific format. It is stored in the memory and identified by the Message Queue identifier.
2. A Message Queue allows one or more processes to write and read messages to it.
3. Both pipelines and named pipelines are communication data first-in-first-out principles.
4. Message queues can be used to query messages at random. messages do not have to be read in the order of first-in-first-out, or they can be read by message type, which is more advantageous than FIFO.
Currently, there are two main types of Message Queues: POSIX message queues and System V message queues. System V message queues are widely used. The System V Message Queue continues with the kernel. The message queue is deleted only when the kernel is restarted or manually deleted.
Ii. Related functions
1. Obtain the key value
Key_t ftok (char * pathname, int projid)
# Include <sys/types. h>
# Include <sys/ipc. h>
Parameters:
Pathname: file name (including path ),It is usually set to the current directory "." For example, if projid is 'A', it is the "./a" file.
Projid: Project ID, which must be a non-0 INTEGER (0-255 ).
2. Create a Message Queue
Int msgget (key_t key, int msgflag)
# Include <sys/types. h>
# Include <sys/ipc. h>
# Include <sys/msg. h>
Function:
Creates a new or opens an existing message queue, which corresponds to the key.
Parameters:
Key: the return value of the function ftok or IPC_PRIVATE.
Msgflag:
IPC_CREAT: Creates a message queue.
IPC_EXCL: used with IPC_CREAT, which indicates that if the message queue to be created already exists, an error is returned.
IPC_NOWAIT: When the read/write message queue requirements cannot be met, it is not blocked.
Return Value:
The queue identifier is returned if the call is successful. Otherwise,-1 is returned.
A new message queue is created in either of the following scenarios:
1. If there is no message queue corresponding to the key-value key, and msgflag contains the IPC_CREAT flag.
2. The key parameter is IPC_PRIVATE.
3. Message Queue attribute Control
Int msgctl (int msqid, int cmd, struct msqid_ds * buf)
Function:
MQ is controlled by cmd.
Parameters:
Msqid: Message Queue ID, Message Queue identifier. This value is the return value of the Message Queue created by msgget.
Cmd:
IPC_STAT: stores the current values of each element in the data structure related to msqid into the structure directed by buf.
IPC_SET: Set the elements in the data structure related to msqid to the corresponding values in the structure pointed to by the buf.
IPC_RMID:DeleteThe message queue indicated by msqid deletes it from the system and destroys the relevant data structure.
Buf: Message Queue Buffer
Struct msqid_ds{
Struct ipc_perm msg_perm;/* Ownership and permissions */
Time_t msg_stime;/* Time of last msgsnd ()*/
Time_t msg_rtime;/* Time of last msgrcv ()*/
Time_t msg_ctime;/* Time of last change */
Unsigned long _ msg_cbytes;/* Current number of bytes in queue (non-standard )*/
Msgqnum_t msg_qnum;/* Current number of messages in queue */
Msglen_t msg_qbytes;/* Maximum number of bytesallowed in queue */
Pid_t msg_lspid;/* PID of last msgsnd ()*/
Pid_t msg_lrpid;/* PID of last msgrcv ()*/
};
Struct ipc_perm{
Key_t key;/* Key supplied to msgget ()*/
Uid_t uid;/* Valid tive 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 */
};
4. send information to the Message Queue
Int msgsnd (int msqid, struct msgbuf * msgp, size_t msgsz, int msgflag)
# Include <sys/types. h>
# Include <sys/ipc. h>
# Include <sys/msg. h>
Function:
Add a new message to the end of the queue to send a message to the message queue.
Parameters:
Msqid: the id of an opened message queue
Msgp: struct pointer for storing messages.
Msgflag: Control attribute of the function.
Message structureMsgbufIs:
Struct msgbuf
{
Long mtype; // Message Type
Char mtext [1]; // the message body, the first address of the message data. The maximum length of this data is 8012. You can regard it as a structure, there are also types and data, which can be parsed when recv is used.
}
Msgsz: the length of the message data.
Msgflag:
IPC_NOWAIT: indicates that msgsnd returns immediately when the message queue does not have enough space for messages to be sent.
0: msgsnd is blocked until the condition is met. (This is generally used)
5. Receive Information from Message Queue
Ssize_t msgrcv (int msqid, struct msgbuf * msgp, size_t msgsz, long msgtype, int msgflag)
# Include <sys/types. h>
# Include <sys/ipc. h>
# Include <sys/msg. h>
Function:
Receive messages from the queue
Parameters:
Msqid: the id of an opened message queue
Msgp: struct pointer for storing messages.Msgp-> mtype is the same as the fourth parameter.
Msgsz: the number of bytes of the message, which specifies the size of mtext.
Msgtype: the value of Message Type mtype. If the value is 0, the first message in the queue is accepted. If the value is smaller than 0, the type of the message that is smaller than the absolute value of the value is accepted. If the value is greater than 0, messages of the specified type are accepted, that is, the message of this value.
Msgflag: Control attribute of the function.
Msgflag:
MSG_NOERROR: If the returned message is more than nbytes bytes, the message will be truncated to nbytes bytes without notifying the message sending process.
IPC_NOWAIT: The call process will return immediately. If no message is received,-1 is returned.
0: msgrcv calls are blocked until the conditions are met.
After a message is successfully read, the message in the queue will be deleted.
Iii. related examples
Example 1: simple sending and receiving test of Message Queue
# Include <sys/types. h>
# Include <sys/msg. h>
# Include <unistd. h>
# Include <string. h>
# Include <stdio. h>
Struct msg_buf {
Int mtype; // Message Type
Char data [255]; // data
};
IntMain(Int argc, char * argv [])
{
Key_t key;
Int msgid;
Int ret;
Struct msg_buf msgbuf;
// Obtain the key value
Key = ftok (".", 'A ');
Printf ("key = [% x] \ n", key );
// Create a message queue
Msgid = msgget (key, IPC_CREAT | 0666 );/* File-based */
If (msgid =-1)
{
Printf ("creat error \ n ");
Return-1;
}
// Send "test data" to the message queue in non-blocking mode based on the current process type
Msgbuf. mtype =Getpid ();
Strcpy (msgbuf. data, "test data ");
Ret = msgsnd (msgid, & msgbuf, sizeof (msgbuf. data), IPC_NOWAIT );
If (ret =-1)
{
Printf ("send message err \ n ");
Return-1;
}
// Receives data in non-blocking mode
Memset (& msgbuf, 0, sizeof (msgbuf ));
Ret = msgrcv (msgid, & msgbuf, sizeof (msgbuf. data), getpid (), IPC_NOWAIT );
If (ret =-1)
{
Printf ("receive message err \ n ");
Return-1;
}
Printf ("receive msg = [% s] \ n", msgbuf. data );
Return 0;
}
Example 2: inter-process Message Queue Communication
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/ipc. h>
# Include <string. h>
# Include <signal. h>
Struct msgbuf {
Int mtype;
Char mtext [100];
};
IntMain(Void)
{
Key_t key;
Pid_t pid;
Int msgid;
Struct msgbuf msg;
Key = ftok (".", 0x01 );
If ((Msgid = msgget (key, IPC_CREAT | 0666)) <0)
{
Perror ("msgget error ");
Exit (1 );
}
// Create a process
If ((Pid = fork ()) <0)
{
Perror ("fork error ");
Exit (1 );
}
// Subprocess receiving information
Else if (pid = 0)
{
While (1)
{
Memset (msg. mtext, 0,100 );
Msgrcv (msgid, & msg, 100, 2, 0 );// Receive the msg from 2
Printf ("\ receive: % s \ n:", msg. mtext );
Fflush (stdout );
}
Exit (0 );
}
// Sends a message to the parent process
Else
{
While (1)
{
Memset (msg. mtext, 0,100 );
Printf ("father :");
Fgets (msg. mtexts, 100, stdin );
If (strncmp ("bye", msg. mtext, 3) = 0) // exit if the first three characters are bye
{
Kill (pid, SIGSTOP );
Exit (1 );
}
Msg. mtype =1; // Send to 1
Msg. mtext [strlen (msg. mtext)-1] = '\ 0 ';
Msgsnd (msgid, & msg, strlen (msg. mtext) + 1, 0 );
}
}
Return 0;
}
The disadvantage of this program is: sending, receiving, and sending. Two threads can be created in the two processes, responsible for receiving and sending, respectively, to complete the communication between processes.