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