"Copyright Notice: respect for the original, reproduced please retain the source: blog.csdn.net/shallnet or .../gentleliu, the article is for learning communication only, do not use for commercial purposes"
System V Message Queuing is similar to POSIX Message Queuing, both of which are supported by both message queues for Linux systems. Let's take a look at System V Message Queuing related operations and their functions.
- The Msgget () function creates a message queue or opens a message queue.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget (key_t key , int msgflg);
The parameter key is Ftok return value or ipc_private; the parameter msgflg is ipc_creat or Ipc_creat | IPC_EXCL, when Message Queuing already exists, and MSGFLG is specified asIpc_creat | IPC_EXCL, the function returns eexist. in each message queue in the system, the kernel maintains such a structure:
struct MSQID_ DS {struct ipc_perm msg_perm; /* Ownership and Permissions */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) */msgqnum_ T Msg_qnum; /* Current number of messages in queue */msglen_t MSG _qbytes; /* Maximum number of bytes allowed in queue */pid_t Msg_lspid; /* PID of Last MSGSND (2) */pid_t msg_lrpid; /* PID of Last MSGRCV (2) */};
where the ipc_perm structure is defined as follows:
struct Ipc_perm { key_t __key; /* Key supplied to Msgget (2) */ uid_t uid; /* Effective UID of Owner */ gid_t gid; /* Effective GID of Owner */ uid_t cuid; /* Effective UID of Creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short __seq; /* Sequence number */ };
When a message queue is initialized, the corresponding structure of the message queue is initialized as follows: Msg_perm.cuid and Msg_perm.uid are set to the user ID of the current process,Msg_perm.cuid and Msg_perm.uid are set to the current process group Id;msg_perm.mode are set to Msgflg;msg_qnum, Msg_lspid, Msg_lrpid, Msg_stime and The msg_rtime is set to 0;msg_ctime is set to the current time; Msg_qbytes is set to the system limit value MSGMNB.
- The msgsnd () function adds a message to the message queue.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd (int msqid , const void *MSGP, size_t msgsz, int msgflg);
The parameter msgqid is the message queue identifier, and the Msgget () returns the value;The parameter MSGP is a pointer to a user-defined struct, and the structure defines the format template as follows:
struct MSGBUF { long mtype; /* Message type, must be > 0 */ char mtext[1]; /* Message data */ };
The mtex field is an array, the size of which is the function parameter Msgsz, and thevalue of mtype must be greater than 0; the structure is defined by the user and is generally defined according to the actual application. The parameter Msgsz is the length of the message to be sent, can be specified as 0, and is generally specified as MSGBUF structure length minus long type length (sizeof (MSGBUF)-sizeof (long)); The parameter MSGFLG is 0, or ipc_nowait,ipc_nowait is non-blocking, and when sent, if the column data is full, the function immediately returns an error Eagain, if MSGFLG is 0, blocks until the message queue is filled with enough space to add a new message. Or Message Queuing is removed from the system or interrupted by a signal.
- The MSGRCV () function reads messages from the message queue.
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t MSGRCV (int Msqid, void *MSGP, size_t msgsz, long Msgtyp, int msgflg);
parameter MsgId same function msgsnd;parameter MSGP pass function function msgsnd, for pointer to receive message struct bodyThe parameter msgsz is the cache size to accept the message;The parameter Msgtyp is the reading of what message, if:0-Reads the oldest message in the message queue and reads the message in FIFO mode. > 0-Read Message queue type isMsgtyp the earliest news. < 0-reads the earliest message in a message queue that has a message type less than or equal to the minimum message type in the Msgtyp absolute value. The parameter MSGFLG is either a value or a few worth or: ipc_nowait-returns immediately if none is in the queue, or if the option is not specified, the function will block until the specified message is readable, or the message queue is removed from the system, or the signal is interrupted; msg_noerror -Truncate message if the received message size is greater than msgsz given value; msg_except-use a Msgtyp greater than 0 to read the message type is notMsgtypThe first message;
The Msgctl () function controls a queue. #include <sys/msg.h> int msgctl (int msqid, int cmd, struct msqid_ds *buf), parameter cmd is the action to be done on the queue, these actions are:
Ipc_stat-Get Message Queuing information, copy the structure of the message queue to msqid from the kernel data structure tothe BUF pointer points to the MSQID_DS structure body. Ipc_set-Sets the msgqid corresponding message queue kernel structure using the structure of the buf point;Ipc_rmid-delete msgqid message queue;Ipc_info,msg_info, Msg_stat see the Linux man function manual. Example:Service process:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <errno.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include "slnmq.h" static int Recv_type, Msgid;int sln_server_loop (void) {int rcvmsg_len; key_t key; struct SLN_MSGBUF slnmsg; Key = Ftok (sln_ipc_mq_name, 0); if (Key < 0) {fprintf (stderr, "Ftok:%s\n", Strerror (errno)); return-1; } MsgId = Msgget (Key, Ipc_creat | IPC_EXCL); if ((MsgId < 0) && (errno! = eexist)) {fprintf (stderr, "Msgget:%s\n", Strerror (errno)); return-1; } if (MsgId < 0) {printf ("Open existing mq!\n"); MsgId = Msgget (key, ipc_creat); if (MsgId < 0) {fprintf (stderr, "Msgget:%s\n", Strerror (errno)); return-1; }} sleep (10); Just for test for (;;) {Rcvmsg_len = MSGRCV (MsgId, &slnmsg, SLN_ipc_mq_msgsize, Recv_type, 0); if (Rcvmsg_len < 0) {fprintf (stderr, "MSGRCV:%s\n", Strerror (errno)); Sleep (1); Continue } fprintf (stdout, "Receive-recv len:%d, msg type:%d, msg:%s\n", Rcvmsg_len, Slnmsg.msgtype, SL NMSG.MSG); } return 0;} static void Sigint_func (int sig) {if (Msgctl (MsgId, Ipc_rmid, NULL) < 0) {fprintf (stderr, "Msgctl:%s\n", St Rerror (errno)); } exit (0);} int main (int argc, const char *argv[]) {FILE *FP = NULL; if (argc! = 2) {fprintf (stderr, "Usage:%s <msg type>\n", argv[0]);//Run, specify the type of message that the service will receive for the process return-1; } Recv_type = Atoi (argv[1]); if (Access (Sln_ipc_mq_name, F_OK) < 0) {fp = fopen (Sln_ipc_mq_name, "w+"); if (NULL! = fp) {fclose (FP); }} signal (SIGINT, sigint_func); The service process captures the interrupt signal, deletes the message queue in the interrupt handler function, and launches the program Sln_server_loop (); return 0;}
Customer Process:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <errno.h> #include "slnmq.h" int sln_msgsnd (int msg_type, const void *sndmsg, int sndlen) {int Msgi D, Rcvmsg_len; key_t key; struct SLN_MSGBUF slnmsg; Key = Ftok (sln_ipc_mq_name, 0); if (Key < 0) {fprintf (stderr, "Ftok:%s\n", Strerror (errno)); return-1; } MsgId = Msgget (key, ipc_creat); if (MsgId < 0) {fprintf (stderr, "Msgget:%s\n", Strerror (errno)); return-1; } slnmsg.msgtype = Msg_type; memcpy (&slnmsg.msg, sndmsg, Sndlen); Msgsnd (MsgId, (void *) &slnmsg, Sndlen, 0);} int main (int argc, const char *argv[]) {int type; if (argc! = 3) {fprintf (stderr, "Usage:%s <msg type> <msg content>\n", argv[0]); return-1; } type = Atoi (argv[1]); SLN_MSGSND (type, argv[2], strlen (argv[2]) + 1); return 0;}
The service process runs first and waits 10 seconds at the start of the read message, and the client process joins several messages to the message queue when the service process has not started reading the data, as follows:
./client 1 abcd./client 2 efghi./client 3 jkl./client 4 mn./client 5 opqrst./client 6 uv./client 7 w./client 8 xyz
When the service process runs, the service process is taken out of the message queue to fetch the message from the type (run-time parameter specified), the following are the message types specified by the server runtime and the messages taken out (the client runs as above):
#./server 0 (Read all messages) Receive- recv len:5, msg type:1, msg:abcdreceive- recv len:6, msg type:2, Msg:efghirec Eive- recv len:4, msg type:3, msg:jklreceive- recv len:3, msg type:4, msg:mnreceive- recv Len:7, msg Type:5, msg:opqrstreceive- recv len:3, msg type:6, msg:uvreceive- recv len:2, msg type:7, msg:wreceive - recv Len:4, msg type:8, MSG:XYZ
#./server 4 (Read message with message Type 4) Open existing mq!receive- recv len:3, msg type:4, MSG:MN
#./server-5 (read message less than 5 message) Open existing mq!receive- recv len:5, msg type:1, msg:abcdreceive- recv le N:6, msg type:2, msg:efghireceive- recv len:4, msg type:3, msg:jklreceive- recv len:3, msg type:4, msg: Mnreceive- recv len:7, msg type:5, Msg:opqrst
When the server does not exit, you can use the System command IPCS to view Message Queuing in the system:
# IPCS------Message Queues--------Key msqid owner perms used-bytes messages 0x001fffde 229376 root 0 0 0
When the user presses CTRL + C, the program deletes the message queue, presses CTRL + C, and then views:
# IPCS------Message Queues--------Key msqid owner perms used-bytes messages
You can see that the deletion in the program is successful.
POSIX Message Queuing is roughly similar to System V Message Queuing, but there are some differences between the two sections: POSIX Message Queuing has a priority concept, System V does not, only the message type of the advanced first out to read the message is Fifo;system V Message Queuing has the concept of message type, and can take out messages according to the message type, and POSIX cannot distinguish the message type; source code download: Click to open the link
About Linux IPC (10): System V Message Queuing