Message Queuing Overview
Message Queuing provides a way to send a piece of data from one process to another (native only);
Each block of data is considered to have a type, and the receiver process receives a data block that can have different type values.
Message Queuing also has the same shortage of pipelines: (1) The maximum number of bytes per message (Msgmax); (2) The total number of message queues in the system also has an upper limit (Msgmni); (3) The total number of bytes that each message queue can hold is capped (msgmnb).
viewing system limits
Cat/proc/sys/kernel/msgmax #最大消息长度限制
CAT/PROC/SYS/KERNEL/MSGMNB #消息队列总的字节数
Cat/proc/sys/kernel/msgmni #消息条目数
Pipeline vs. Message Queuing
Pipeline |
News |
Flow pipeline |
Have borders |
Advanced First Out |
Can last in first out |
IPC Object Data structure
The kernel maintains a data structure for each IPC object 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 */};
Message Queuing-specific struct struct msqid_ds{ struct ipc_perm msg_perm; /* Ownership and permissions The data structures shared by various IPC objects */ 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) message queue currently Number of bytes saved */ msgqnum_t msg_qnum; /* Current number of messages held in the messages in queue message Queue */ msglen_t msg_qbytes; /* Maximum number of bytes allowed in queue message queue maximum allowed bytes */ pid_t msg_lspid; /* PID of Last MSGSND (2) */ pid_t msg_lrpid; /* PID of Last MSGRCV (2) */};
Message Queuing representation in the kernel
Messages are saved as a list in the message queue, and each node type resembles the following:
struct msq_node{ Type msq_type; Type length Msg_len;//lengths Data Msg_data; Data struct msg_node *next;};
Message Queuing API
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>int msgget (key_t key, int msgflg); int Msgctl (int msqid, int cmd, struct msqid_ds *buf), int msgsnd (int msqid, const void *MSGP, size_t msgsz, int msgflg); ssize_t MSGRCV (int msqid, void *msgp, size_t msgsz, long Msgtyp, int msgflg);
Msgget
function: Used to create and access a message queue
int Msgget (key_t key, int msgflg);
Parameters:
Key: The name of a message queue
MSGFLG: Consisting of nine permission flags, such as 0644, whose usage is the same as the mode pattern flag used when creating the file (but Message Queuing does not have X (execute) permission)
return value:
Successfully returns the message queue number, which is the identification code for the message queue; 1 failure return
Msgget Call graph
/** Example 1: Specify Ipc_creat at MSGFLG, if the message queue is not present, create a **/int main (int argc, char *argv[]) { //specify Ipc_creat, or create a message queue if it does not exist int msgid = msgget (1234, 0666| Ipc_creat); if (MsgId = =-1) err_exit ("Msgget error"); cout << "msgget success" << Endl;}
/** Example 2:ipc_creat| IPC_EXCL, if the message queue already exists, an error is returned **/int main (int argc, char *argv[]) { //Specify IPC_EXCL, if already present, the report file already exists (error) int msgid = Msgget (1234, 0666| Ipc_creat| IPC_EXCL); if (MsgId = =-1) err_exit ("Msgget error"); cout << "msgget success" << Endl;}
/** Example 3: After the key is specified as Ipc_private (with a value of 0) and the key is specified as Ipc_private, then Msgget will create a new message queue, and the descriptor for each message queue created is different! Therefore, unless MessageID (key) is passed to another process (unless there is an associated process), other processes cannot use the message queue (except Blood fork). Therefore, the message queue created by Ipc_private can only be used in processes that are related to the current process!**/int Main (int argc, char *argv[]) { //specify ipc_private int msgid = Msgget (Ipc_private, 0666| Ipc_creat| IPC_EXCL); if (MsgId = =-1) err_exit ("Msgget error"); cout << "msgget success" << Endl;}
/** Example 4: When opening a message queue only, the MSGFLG option can be ignored (0), which is opened with the permission to create the message queue **/int main (int argc, char *argv[]) { int msgid = msgget (1234 , 0); if (MsgId = =-1) err_exit ("Msgget error"); cout << "msgget success" << Endl; cout << "MsgId =" << msgid << Endl;}
Example 5: Low privilege creation, high privilege open int main () { //low rights create int msgid = Msgget (0x255,0444 | Ipc_creat); if (MsgId < 0) err_exit ("Mesget error"); else cout << "Create Mes OK, MsgId =" << msgid << Endl; High privilege open MsgId = msgget (0x255,0644 | Ipc_creat); if (MsgId < 0) err_exit ("Mesget error"); else cout << "Create Mes OK, MsgId =" << msgid << Endl;}
Msgctl function
function: Get/Set Message queue information
int msgctl (int msqid, int cmd, struct msqid_ds *buf);
Parameters:
MSQID: Message Queue identification code returned by the Msgget function
CMD: Is the action that will be taken (see below)
CMD: The action to be taken (there are three desirable values), respectively, as follows:
/** example 1:ipc_ RMID, deleting Message Queuing Note: Message Queuing does not use the function of "reference count" **/int main () {int msgid = msgget (1234, 0); if (MsgId = =-1) err_exit ("Msgget error"); if (Msgctl (MsgId, Ipc_rmid, NULL) = =-1) err_exit ("Msgctl ipc_rmid error"); cout << "Msgctl ipc_rmid Success" << Endl;}
/** example 2:ipc_ Stat**/int Main () {int msgid = Msgget (0x255, 0666| Ipc_creat); if (MsgId = =-1) err_exit ("Msgget error"); struct Msqid_ds buf; if (Msgctl (msgid,ipc_stat,&buf) = =-1) err_exit ("Msgctl error"); printf ("Buf.msg_perm.mode =%o\n", buf.msg_perm.mode); %o print printf in octal ("Buf.__key =%x\n", Buf.msg_perm.__key); %x is printed in hexadecimal cout << "buf.__msg_cbytes =" << buf.__msg_cbytes << Endl; cout << "buf.msg_qbytes =" << buf.msg_qbytes << Endl; cout << "buf.msg_lspid =" << buf.msg_lspid << Endl;}
/** Practice: Ipc_set, generally need to get first, and then set **/int main () { int msgid = msgget (0x255, 0); if (MsgId = =-1) err_exit ("Msgget error"); Gets the properties of the message queue struct Msqid_ds buf; if (Msgctl (msgid,ipc_stat,&buf) = =-1) err_exit ("Msgctl error"); Set the properties of Message Queuing buf.msg_perm.mode = 0600; if (Msgctl (MsgId, Ipc_set, &buf) = =-1) err_exit ("Msgctl error"); Get and print bzero (&buf, sizeof (BUF)); if (Msgctl (MsgId, Ipc_stat, &buf) = =-1) err_exit ("Msgctl ipc_stat error"); printf ("mode =%o\n", Buf.msg_perm.mode);}
Attached-View IPC objects in the system
IPCs
Delete Message Queuing
Ipcrm-q [Msqid]
or Ipcrm-q [key] #如果key不等于0的话
Linux IPC Practice (4)--system v Message Queuing (1)