System v ipc (1)-message queue, ipc queue
I. Overview
System v ipc: Message Queue, semaphore, and shared memory. These three kinds of IPC first appeared on AT&T System v UNIX and followed the XSI standard, sometimes known as xsi ipc.
This article first explores Message Queues:
1. MQ allows processes to exchange data in the form of messages. Reading and writing are all for the entire message and cannot read or write a part of the message. Unlike the pipeline, you can read and write any byte in the form of a stream.
2. In addition to data, a message queue also has an integer to indicate the type of the message. When reading a message, you can read the message in the FIFO mode or by the message type.
Ii. Function Interfaces
1. Create a Message Queue
1 #include <sys/msg.h>2 3 int msgget(key_t key, int msgflg);
Key: an integer. This function converts the key into an IPC identifier. Key can be defined in three ways: 1. Manually specify an integer at will. 2. Input IPC_PRIVATE as a key, which is automatically generated by the system. 3. Use the ftok () function.
Msgflg: Specifies the message permission, which is similar to File Permission control.
2. Send messages
1 #include <sys/msg.h>2 3 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
Msqid: The id obtained by msget.
Mgsp: Structure pointer for storing messages. The following mtype is the custom message type, and mtext is the message data.
1 struct msgbuf {2 long mtype; /* message type, must be > 0 */3 char mtext[1]; /* message data */4 };
Msgsz: Message Size, corresponding to the mtext in msgbuf above.
Msgflg: controls the exception status when a message is sent, such as the message queue is full.
3. receive messages
1 #include <sys/msg.h>2 3 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
Msqid: The id obtained by msget () or a known Message ID.
Msgp, msgsz: Same as msgsnd ().
Msgtyp: the type of message received, that is, mtype in msgbuf. But there are other usage:
If the value is 0, the first available message in the queue is obtained.
If the value is greater than 0, the first message of the same type is obtained, that is, mtype.
If the value is less than 0, the first message that is equal to or less than the absolute value of mtype is obtained. We will perform experiments one by one.
Msgflg: Same as msgsnd ().
4. Message Control
1 #include <sys/msg.h>2 3 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
Cmd: There are three options: IPC_STAT, IPC_SET, and IPC_RMID. The first two are the message structures corresponding to msgid and the last one is to delete the message queue.
3. Simple Example
1. Create a Message Queue
1 /** 2 * @file msg_create.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 void err_exit(const char *err_msg)11 {12 printf("%s error\n", err_msg);13 exit(1);14 }15 16 int main(void)17 {18 int msg_id = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);19 if (msg_id == -1)20 err_exit("msgget()");21 22 printf("create msg_id:%d\n", msg_id);23 24 return 0;25 }
2. Send messages
1 /** 2 * @file msg_send.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 #define MAX_BUFFER 102411 12 typedef struct13 {14 long msg_type;15 char msg_text[MAX_BUFFER];16 } msg_t;17 18 void err_exit(const char *err_msg)19 {20 printf("%s error\n", err_msg);21 exit(1);22 }23 24 int main(int argc, char *argv[])25 {26 if (argc < 4)27 {28 printf("usage: %s msg_id msg_type msg_text\n", argv[0]);29 exit(1);30 }31 32 int msg_id = atoi(argv[1]);33 msg_t send_msg;34 char *text = argv[3];35 int text_len = strlen(text);36 37 send_msg.msg_type = atoi(argv[2]);38 memcpy((void *)send_msg.msg_text, text, text_len);39 40 if (msgsnd(msg_id, &send_msg, text_len, 0) == -1)41 err_exit("msgsnd()");42 43 return 0;44 }
3. receive messages
1 /** 2 * @file msg_recv.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/msg.h> 9 10 #define MAX_BUFFER 102411 12 typedef struct13 {14 long msg_type;15 char msg_text[MAX_BUFFER];16 } msg_t;17 18 void err_exit(const char *err_msg)19 {20 printf("%s error\n", err_msg);21 exit(1);22 }23 24 int main(int argc, const char *argv[])25 {26 if (argc < 3)27 {28 printf("usage: %s msg_id msg_type\n", argv[0]);29 exit(1);30 }31 32 int msg_id = atoi(argv[1]);33 msg_t recv_msg;34 long msg_type = atoi(argv[2]);35 36 if (msgrcv(msg_id, &recv_msg, MAX_BUFFER, msg_type, 0) == -1)37 err_exit("msgrcv()");38 39 printf("receive:%s\n", recv_msg.msg_text);40 41 //if (msgctl(msg_id, IPC_RMID, 0) == -1)42 // err_exit("msgctl()");43 44 return 0;45 }
Iv. Experiment
1. Create a message, compile and execute msg_create.c, and use ipcs-q to view the message:
As you can see, msqid is passed in using IPC_PRIVATE as the key, which is automatically generated by the system, and msqid = 262144 is used to receive messages. Perms is the permission set by our code. At this time, the message bytes and number of messages are both 0.
2. Send the message, compile and execute msg_send.c, and send the message. Use ipcs-q to view the message:
Above./mes_send is followed by the id, type, and data of the created message queue.
Next, we will continue to send one type of message, two types of messages, two types of messages, and three types of messages. We will wait for them to receive messages and perform experiments.
Now we have 6 messages.
3. receive the message and compile msg_recv.c. We will mainly experiment with the msg_type parameter in msgrcv. That is, the first line of code of the file.
3.1: When msg_type is equal to 0, obtain the first available message in the queue.
As you can see, 1234 is the message that I sent to the queue for the first time.
3.2: When msg_type is greater than 0, obtain the first message of the same type:
The above is a 3 type message, and the haha that receives the first sent 3 message.
3.3: When msg_type is less than 0, obtain the first message equal to or less than the absolute value of msg_type:
In the above example, the absolute value of-3 is 3, and the first message in the queue is 22222 of Message 1 (originally 1234 of Message 1). We just read it during our experiments, so it is left first ). 1 is less than 3, so Message 1 is read.
4. Delete the message queue. There are 41st lines of code in msg_recv.c. If the code is compiled and executed after the message is released, the entire queue is deleted after a message is received.