Linux IPC Practice (7)--posix Message Queuing

Source: Internet
Author: User
Tags message queue posix

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, &amp    , 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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.