Linux IPC 消息队列

 管道和FIFO是字节流,没有消息边界。

1. Posix 消息队列

/* mq_open - open 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); mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
/*  mq_send, mq_timedsend - send a message to a message queue */ #include
<mqueue.h> int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); #include <time.h> #include <mqueue.h> int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout);
/* mq_receive, mq_timedreceive - receive a message from a message queue */ #include
<mqueue.h> ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); #include <time.h> #include <mqueue.h> ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout);
/* mq_getattr, mq_setattr - get/set message queue attributes */
#include <mqueue.h>
int mq_getattr(mqd_t mqdes, struct mq_attr *attr); int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr); struct mq_attr { long mq_flags; /* Flags: 0 or O_NONBLOCK */ long mq_maxmsg; /* Max. # of messages on queue */ long mq_msgsize; /* Max. message size (bytes) */ long mq_curmsgs; /* # of messages currently in queue */ };
/* mq_notify - register for notification when a message is available */
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);

/* mq_unlink - remove a message queue */
int mq_unlink(const char *name); Link with
-lrt.

Posix消息队列注意事项

1. mq_setattr只能修改mq_flags为阻塞或非阻塞,其他的参数只能通过mq_open在建立消息队列时指定

2. mq_receive每次都返回队列中最高优先级的最早消息

3. mq_notify支持注册一个信号或者线程,在一个消息被加入到一个空队列时发送信息或者激活线程(System V消息队列不提供类似的形式)

2. System V 消息队列

/* msgget - get a System V message queue identifier */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

/* ftok - convert a pathname and a project identifier to a System V IPC key */
#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);

/* msgrcv, msgsnd - System V message queue operations */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

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);

/* msgctl - System V message control operations */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

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) */
};

System V消息队列注意事项

1. msgsnd的flag参数可以指定为IPC_NOWAIT。IPC_NOWAIT标志使得此次msgsnd操作为非阻塞:如果没有新消息的存放空间,函数立即返回一个EAGIN错误,出现这种情况的情形如下:

a. 在该消息队列中已经有太多的字节(对应struct msqid_ds中的msg_qbytes)

b. 在系统范围内存在太多的消息

如果出现上述两个条件之一,且msgsnd未指定IPC_NOWAIT标志,那么调用线程被投入睡眠,直到:

a. 具备存放新消息的空间

b. 指定的消息队列被消除了(这种情况下msgsnd返回ERMID错误)

c. 调用线程被某个捕获的信号中断(这种情况msgsnd返回EINTR错误)

 

2. msgrcv的flag参数也可以指定为IPC_NOWAIT,还有另一个标志 MSG_NOERROR:当所接收的消息数据部分大于msgrcv的length参数,如果设置了MSG_NOERROR,数据被截断,msgrcv函数不会出错;如果没有设置该标志,msgrcv函数返回E2BIG错误。

 

3. msgctl的cmd可以取值如下:

IPC_RMID: 删除指定队列

IPC_SET: 支持设置指定队列的 msgid_ds结构体中的 msg_prem.uid, msg_prem.gid, msg_prem.mode 和 msg_qbytes

IPC_STAT: 返回指定队列的msgid_ds 结构

 

4. system V 消息队列的限制

可以查看proc/sys/kernel/文件夹下的msgmax  msgmni  msgmnb

也可以通过ipcs  -l 命令查看:

ubuntu: ipcs -l

------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 32768
max total shared memory (kbytes) = 8388608
min seg size (bytes) = 1

------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767

------ Messages Limits --------
max queues system wide = 1717                 系统范围内的消息队列最大数量:msgmni
max size of message (bytes) = 8192            每个消息的最大字节数:msgmax
default max size of queue (bytes) = 16384   每个消息队列上的最大字节数:msgmnb
原文地址:https://www.cnblogs.com/xiaokuang/p/4613363.html