首页 > 代码库 > Linux消息队列基础
Linux消息队列基础
消息队列基本概念
消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限与本机)
每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)
管道 vs. 消息队列:
管道: 流管道 消息: 有边界
先进先出 可以后进入、先出来
消息队列大小三大限制
cat /proc/sys/kernel/msgmax #最大消息长度限制
cat /proc/sys/kernel/msgmnb #消息队列总的字节数
cat /proc/sys/kernel/msgmni #消息条目数
IPC对象数据结构
内核为每个IPC对象维护一个数据结构
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 */ };
消息队列特有的结构
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) */ };
消息队列在内核中的表示
消息队列函数示例
msgget函数
功能:用来创建和访问一个消息队列
原型:
int msgget(key_t key, int msgflg);
参数:
key: 某个消息队列的名字
msgflg:由九个权限标志构成,如0644,它们的用法和创建文件时使用的mode模式标志是一样的(但是消息队列没有x(执行)权限)
返回值:
成功返回消息队列编号,即该消息队列的标识码;失败返回-1
编程实践
//实践1: IPC_PRIVATE:宏,值为0 int main() { //IPC_PRIVATE每次创建的消息队列的描述符都是不同的! //因此,计时MessageID(key)传送给其他进程(除非有关联的进程), //其他进程也无法使用该消息队列(血缘fork除外) int msgid = msgget(IPC_PRIVATE,0666); if (msgid < 0) { //如果消息队列不存在,则打开错误,errno=ENOENT if (errno == ENOENT) { cout << "ENOENT" << endl; } err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0; } /** IPC_PRIVATE创建的消息队列,只能用在与当前进程有关系的进程中使用! */
//实践2: IPC_CREAT int main() { //指定IPC_CREAT,则一定会创建消息队列 int msgid = msgget(0x1235,0666|IPC_CREAT); if (msgid < 0) { //如果消息队列不存在,则打开错误,errno=ENOENT if (errno == ENOENT) { cout << "ENOENT" << endl; } err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0; }
//实践3: IPC_CREAT|IPC_EXCL int main() { //指定IPC_EXCL, 如果已经存在,则报告文件已经存在(错误) int msgid = msgget(0x1235,0666|IPC_CREAT|IPC_EXCL); if (msgid < 0) { err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0; }
//实践4:低权限创建,高权限打开 int main() { //低权限创建 int msgid = msgget(0x255,0444 | IPC_CREAT); if (msgid < 0) { err_exit("mesget error"); } else { cout << "Create Mes OK, msgid = " << msgid << endl; } //高权限打开 msgid = msgget(0x255,0644 | IPC_CREAT); if (msgid < 0) { err_exit("mesget error"); } else { cout << "Create Mes OK, msgid = " << msgid << endl; } return 0; }
msgget函数参数关系图
msgctl函数
功能:对消息队列进行控制
原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msqid: 由msgget函数返回的消息队列标识码
cmd:是将要采取的动作(见下)
返回值:
成功返回0,失败返回-1
cmd:将要采取的动作(有三个可取值),分别如下:
Linux消息队列基础