Linux inter-process communication: Message Queue and linux Process Communication queue
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), usually set to the current directory "."
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: deletes a Message Queue indicated by msqid, removes 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.
The message structure msgbuf is:
Struct msgbuf
{
Long mtype; // Message Type
Char mtext [1]; // message body, the first address of the message data
}
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.
Msgsz: the number of bytes of the message, which specifies the size of mtext.
Msgtype: the value of Message Type mtype.
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.
For example, simple message sending and receiving
# Include <sys/types. h>
# Include <sys/msg. h>
# Include <unistd. h>
# Include <string. h>
# Include <stdio. h>
Struct msg_buf
{
Int mtype;
Char data [255];
};
Int main (int argc, char * argv [])
{
Key_t key;
Int msgid;
Int ret;
Struct msg_buf msgbuf;
// Get key
Key = fork (".", "");
Printf ("key = [% x] \ n", key );
// Create quee
Msgid = msgget (key, IPC_CREATE | 0666 );
If (msgid =-1)
{
Printf ("create err! \ N ");
Return-1;
}
// Send "test data" to the message queue in non-blocking mode based on the current process type
Msgbuf. mtype = getpid ();
Stpcpy (msgbuf. data, "test data ");
Ret = msgsnd (msgid; & msgbuf, sizeof (msgbuf. data), IPC_NOWAIT );
If (ret =-1)
{
Printf ("send err! \ N ");
Return-1;
}
// Receives data in non-blocking mode
Memset (& msgbuf, 0x00, sizeof (msgbuf ));
Ret = msgrcv (msgid, & msgbuf, sizeof (msgbuf. data), getpid (), IPC_NOWAIT );
If (ret =-1)
{
Printf ("rcv_err ret = [% d]! \ N ", ret );
Return-1;
}
Printf ("receive msg = [% s] \ n! ", Msgbuf. data );
Return 0;
}
Communication in the same message queue:
# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/ipc. h> // Add this header file
Struct msgbuf {
Long mtype;
Char mtext [100];
}; // Message type and content structure
Int main ()
{
Key_t key;
Int msgid;
Struct msgbuf msg1, msg2; // msg1 for sending and msg2 for receiving
Key = ftok (".", 0xf0); // get the message queue identifier
If (msgid = msgget (key, IPC_CREAT | 0666) <0) // create a message queue
{
Perror ("msgget error ");
Exit (1 );
}
Msg1.mtype = 1; // The message type is 1, which can distinguish multiple messages.
Memset (msg1.mtext, 0,100); // clears the array 0
Strcpy (msg1.mtext, "hello"); // use strcpy to assign values to the Message Content
Msgsnd (msgid, & msg1, strlen (msg1.mtext) + 1, 0); // Add '\ 0' at the end of the message'
Printf ("send % s \ n", msg1.mtext );
Msgrcv (msgid, & msg2, 100, 1, 0); // receives a message sent from 1 and stores it in msg2.
Printf ("receive % s \ n", msg2.mtext );
Msgctl (msgid, IPC_RMID, NULL); // Delete A Message Queue
Return 0;
}
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];
};
Int main ()
{
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 ("\ rbbb: % s \ naaa:", msg. mtext );
Fflush (stdout );
}
Exit (0 );
}
// Sends a message to the parent process
Else
{
While (1)
{
Memset (msg. mtext, 0,100 );
Printf ("aaa :");
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;
}