1. Create/Get a message queue
#include <fcntl.h>/ * for o_* constants */#include <sys/stat.h>/ * for Mode constants */#include < mqueue.h>mqd_t mq_open (const char *name, int oflag);//dedicated to opening a message queue mqd_t mq_open (const char *name, int oflag, mode_t mode , struct mq_attr *attr);
Parameters:
Name: Message queue names;
Oflag: With the Open function type, can be o_rdonly, o_wronly, O_RDWR, can also be bitwise OR on o_creat, O_EXCL, O_nonblock.
Mode: If Oflag specifies O_creat, the mode parameter needs to be specified;
attr: Specifies the properties of the message queue;
return value:
Success: Returns the message queue file descriptor;
Failure: return-1;
Note-posix IPC Name limitations:
1. Must start with "/", and can not be followed by "/", shape such as:/file-name;
2. Name length cannot exceed Name_max
3. When linking: Link WITH-LRT.
/** System V Message Queuing
Create/Open Message Queuing with Msgget
int Msgget (key_t key, int msgflg);
**/
2. Close a message queue
int Mq_close (mqd_t mqdes);/** System V Message Queuing does not resemble this function call **/
3. Delete a message queue
int Mq_unlink (const char *name),/** System V message queue via Msgctl function, and cmd specified as ipc_rmid to implement int msgctl (int msqid, int cmd, struct MSQI D_ds *buf); **/
Example int main () { mqd_t mqid = Mq_open ("/abc", o_creat| O_rdonly, 0666, NULL); if (mqid = =-1) err_exit ("Mq_open error"); cout << "Mq_open success" << Endl; Mq_close (mqid); Mq_unlink ("/abc"); cout << "unlink success" << Endl;}
4. Get / Set Message Queuing properties
int mq_getattr (mqd_t mqdes, struct mq_attr *attr), int mq_setattr (mqd_t mqdes, struct mq_attr *newattr, struct Mq_att R *oldattr);
Parameters:
Newattr: Properties that need to be set
Oldattr: The original attribute
struct mq_attr struct description struct mq_attr{ long mq_flags; /* flags:0 or O_nonblock */ long mq_maxmsg; /* Max. # of messages on queue: Message Queue The number of messages that can be saved */ long mq_msgsize; /* Max. Message size (bytes): Maximum length of message */ long mq_curmsgs; /* # of messages currently in queue: Message Queue Current number of messages saved */};
/** System V Message Queuing
The MSGCTL function is passed and the CMD is specified as Ipc_stat/ipc_set to implement the
int msgctl (int msqid, int cmd, struct msqid_ds *buf);
**/
/** Example: Get the properties of a message queue **/int main (int Argc,char **argv) { mqd_t mqid = Mq_open ("/test", o_rdonly| O_creat, 0666, NULL); if (mqid = =-1) err_exit ("Mq_open error"); struct mq_attr attr; if (Mq_getattr (mqid, &attr) = =-1) err_exit ("mq_getattr error"); cout << "Max messages on queue:" << attr.mq_maxmsg << Endl; cout << "Max message size:" << attr.mq_msgsize << Endl; cout << "Current messages:" << attr.mq_curmsgs << Endl; Mq_close (mqid); return 0;}
5. Send a message
int Mq_send (mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
Parameters:
MSG_PTR: Pointer to a message that needs to be sent
Msg_len: Message length
Msg_prio: Priority of messages
/** System V Message Queuing
Sending messages via the MSGSND function
int msgsnd (int msqid, const void *MSGP, size_t msgsz, int msgflg);
**/
/** Example: Send a message to a message queue, Prio need to read **/struct student{Char name[36] from command-line arguments ; int age;}; int main (int argc,char **argv) { if (argc! = 2) err_quit ("./send <prio>"); mqd_t mqid = Mq_open ("/test", o_wronly| O_creat, 0666, NULL); if (mqid = =-1) err_exit ("Mq_open error"); struct Student stu = {"Xiaofang",%}; unsigned prio = atoi (argv[1]); if (Mq_send (mqid, (const char *) &stu, sizeof (STU), prio) = =-1) err_exit ("Mq_send error"); Mq_close (mqid); return 0;}
6. Reading messages from the message queue
ssize_t mq_receive (mqd_t mqdes, Char *msg_ptr, size_t msg_len, unsigned *msg_prio);
Parameters:
Msg_len: Read the length of the message, note: This value must be equal to the value of mq_attr::mq_msgsize, which can be obtained through mq_getattr, but is generally 8192 bytes [This must be greater than the Mq_ Msgsize attribute of the queue (see Mq_getattr (3)).
Msg_prio: Saving the priority of the obtained message
return value:
Success: Returns the number of bytes of the read message
Failure: Return-1
Note: The read is always the highest priority message in the message queue, and if it is not specified as non-blocking mode, the mq_receive will block;
/** System V Message Queuing
The MSGRCV function is implemented to send the message
ssize_t MSGRCV (int msqid, void *msgp, size_t msgsz, long Msgtyp, int msgflg);
**/
/** Example: Getting a message from a message queue **/int main (int Argc,char **argv) { mqd_t mqid = Mq_open ("/test", o_rdonly); if (mqid = =-1) err_exit ("Mq_open error"); struct Student buf; int NRCV; unsigned prio; struct mq_attr attr; if (Mq_getattr (mqid, &attr) = =-1) err_exit ("mq_getattr error"); if (NRCV = Mq_receive (mqid, (char *) &buf, attr.mq_msgsize, &prio)) = =-1) err_exit ("mq_receive error"); C11/>cout << "Receive" << NRCV << "bytes, priority:" << prio << ", Name:" << Buf.name << ", Age:" << buf.age << Endl; Mq_close (mqid); return 0;}
7. Create/delete message arrival notification events
int mq_notify (mqd_t mqdes, const struct sigevent *SEVP);
Parameter SEVP:
NULL: Indicates revocation of registered notice;
Non-null: Indicates that when the message arrives and the message queue is currently empty, it will be notified;
Notification Method:
1. Generate a signal that you need to bind yourself
2. Create a thread to execute the specified function
Note: This type of registration only generates message notification events when Message Queuing is empty to non-empty, and this is a one-time registration Method!
sigevent struct struct sigevent{ int sigev_notify;/* Notification method */ int Sigev_signo; /* Notification Signal */ Union sigval Sigev_value; /* Data passed with notification * /Void (*sigev_notify_function) (Union sigval); /* Function used for thread notification (sigev_thread) */ void *sigev_notify_attributes;/* Attributes for not Ification Thread (sigev_thread) */ pid_t sigev_notify_thread_id;/* ID of thread to signal (sigev_thread_id) */ };union sigval/ * Data passed with notification */{ int sival_int; /* Integer value */ void *sival_ptr; /* Pointer value * *};
Sigev_notify representative Notice way: Generally used two kinds of values: sigev_signal, to signal the way of notification; Sigev_thread, notify by thread
If you are notified by signal: You need to set two parameters:
Sigev_signo: Code of the Signal
Sigev_value: Additional data for the signal (real-time signal)
If you are notified by thread: You need to set the following two parameters:
Sigev_notify_function
Sigev_notify_attributes
/** Posix IPC-specific features, System v no **/
/** Example: Run the following program a few more times, especially when Message Queuing "from empty, non-empty", multiple "from empty", when the message queue is not empty when running the program, observe the state of the program; **/mqd_t Mqid;long size;void sigHandlerForUSR1 (int signo) {//Data reading is transferred to the response function of the signal SIGUSR1 to struct Student buf; int NRCV; unsigned prio; if (NRCV = Mq_receive (mqid, (char *) &buf, size, &prio)) = =-1) err_exit ("Mq_receive error"); cout << "Receive" << NRCV << "bytes, priority:" << prio << ", Name:" << bu F.name << ", Age:" << buf.age << Endl;} int main (int argc,char **argv) {//Install signal response function if (signal (SIGUSR1, sigHandlerForUSR1) = = Sig_err) err_exit ("sign Al error "); Mqid = Mq_open ("/test", o_rdonly); if (mqid = =-1) err_exit ("Mq_open error"); Gets the maximum length of the message struct mq_attr attr; if (Mq_getattr (mqid, &attr) = =-1) err_exit ("Mq_getattr error"); size = Attr.mq_msgsize; Register message arrival notification event struct Sigevent event; Event.sigev_notify = sigev_signal; Specify to notify EVENT.SIGEV_ by signalingSigno = SIGUSR1; Specify to SIGUSR1 notify if (Mq_notify (mqid, &event) = =-1) err_exit ("Mq_notify error"); Dead Loop, waiting for the signal to arrive while (true) pause (); Mq_close (MQID); return 0;}
/** Example: multiple registration notify, so that can receive the message many times, but still can not be received from the queue non-empty time, the program is modified as follows: **/mqd_t mqid;long size;struct sigevent event;void sigHandlerForUSR1 (int signo) {//NOTE: It is registered before the message is read,//Otherwise the program does not sense the message queue "from space-to-non-empty" a process has changed if (Mq_notify (Mqid, & , event) = =-1) err_exit ("Mq_notify error"); The reading of the data is transferred to the response function of the signal SIGUSR1 to the struct Student buf; int NRCV; unsigned prio; if (NRCV = Mq_receive (mqid, (char *) &buf, size, &prio)) = =-1) err_exit ("Mq_receive error"); cout << "Receive" << NRCV << "bytes, priority:" << prio << ", Name:" << bu F.name << ", Age:" << buf.age << Endl;} int main (int argc,char **argv) {//Install signal response function if (signal (SIGUSR1, sigHandlerForUSR1) = = Sig_err) err_exit ("sign Al error "); Mqid = Mq_open ("/test", o_rdonly); if (mqid = =-1) err_exit ("Mq_open error"); Gets the maximum length of the message struct mq_attr attr; if (Mq_getattr (mqid, &attr) = =-1) err_exit ("Mq_getattrError "); size = Attr.mq_msgsize; Register message arrival Notification event Event.sigev_notify = sigev_signal; Specifies to notify Event.sigev_signo = SIGUSR1 by means of signaling; Specify to SIGUSR1 notify if (Mq_notify (mqid, &event) = =-1) err_exit ("Mq_notify error"); Dead Loop, waiting for the signal to arrive while (true) pause (); Mq_close (MQID); return 0;}
Mq_notify Note Summary:
1. Only one process can be registered as a notification to receive a given queue at any time;
2. When a message arrives at a previously empty queue, and there is already a process registered as a notification to receive the queue, only the notification will be issued if no thread is blocking the mq_receive call of that queue;
3. When the notification is sent to its registration process, the registration of the process is revoked. The process must call Mq_notify again to reregister (if necessary), but be aware that re-registration is placed before the message is read from the message queue and not after (as with the example program);
Attached-View the POSIX message queue that has been successfully created
#其存在与一个虚拟文件系统中, you need to attach it to your system to view
mounting the message queue filesystem On Linux, message queues is created in a Virtual filesystem .
(Other implementations-also provide such a feature, but the details is likely to differ.) This
The file system can be mounted (by the Superuser, note that using the root user is successful) using the following commands:
Mkdir/dev/mqueue
Mount-t Mqueue None/dev/mqueue
You can also use cat to view the status of the message queue, RM Delete:
Cat/dev/mqueue/abc
RM ABC
You can also umount the file system
Umount/dev/mqueue
Attached-makefile
. Phony:clean ALLCC = g++cppflags =-wall-gbin = Mainsources = $ (bin.=.cpp) All: $ (BIN)%.O:%.c$ (CC) $ (cppflags)-C $^-O [ Email protected]main:main.o$ (CC) $ (cppflags) $^-lrt-o [email protected]clean:-rm-rf $ (BIN) *.O Bin/obj/core
Linux IPC Practice (7)--posix Message Queuing