消息队列 IPC 原理

消息队列是消息的链式队列,如下图为消息队列的模型。整个消息队列有两种类型的数据结构。

1.msqid_ds 消息队列数据结构:描述整个消息队列的属性,主要包括整个消息队列的权限、拥有者、两个重要的指针(分别指向消息队列的第一个消息和最后一个消息)。

2.msg 消息队列数据结构:整个消息队列的主体,一个消息队列有若干个消息,每个消息数据结构的基本成员包括消息类型、消息大小、消息内容指针和下一个消息数据结构的位置。

消息队列还可以基于类型处理,但是,消息队列的 FIFO 原则仅仅适用于同类型的消息。在 Linux 中,对消息队列进行了以下规定(不同 Linux 版本的话值可能会不同):

1.默认情况下,整个系统最多允许有16个消息队列。
2.每个消息队列最大为16384字节。
3.消息队列中的每个消息最大为8192字节。

这些内容在 /usr/include/linux/msg.h 中进行定义:

#define MSGMNI    16   /* <= IPCMNI */     /* max # of msg queue identifiers */
#define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
#define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
消息队列的基本属性

下图出于 /usr/include/linux/msg.h 文件

消息队列管理

1.创建消息队列:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> /* 第一个参数为key值,一般由ftok()函数获得;第二个参数为访问权限 */
int msgget(key_t key, int msgflg);

2.消息队列属性控制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> /*
* 第一个参数为消息队列ID,由msgget获得
* 第二个参数为控制指令
* 第三个参数为数据传递的载体
*/
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

控制指令如下:

3.发送消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> /*
* 第一个参数为消息队列ID
* 第二个参数 msgp 指向定义的缓冲区
* 第三个参数为发送消息的大小
* 第四个参数一般高为0,阻塞调用进程
*/
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

4.从消息队列接收消息

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> /*
* 第一个参数为消息队列ID
* 第二个参数为临时消息数据结构,用于储存消息
* 第三个参数为接收消息的大小
* 第四个参数用于指定请求的消息类型
* 第五个参数一般设置为0,阻塞调用进程
*/
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

其中消息数据结构应定义如下:

/* From /usr/include/linux/msg.h */

struct msgbuf {
long mtype; /* 消息类型 */
char mtext[1]; /* 存储消息位置,需要重新定义 */
};
消息队列应用实例

创建两个进程,使用消息队列进行通信,一个进程发送消息,另一个进程接收消息。

发送端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h> struct msgbuf {
long mtype;
char mtext[50];
}; int main()
{
int key, msg_id;
static struct msgbuf buf; key = ftok(".", 1); msg_id = msgget(key, IPC_CREAT | 0600); /* 设置消息的类型 */
buf.mtype = 1; while(1){ fgets(buf.mtext, 50, stdin); /* 输入quit退出进程,并删除队列 */
if(!strncmp(buf.mtext, "quit", 4)){
//msgctl(msg_id, IPC_RMID, 0);
exit(0);
} /* 将消息发送到队列 */
msgsnd(msg_id, (void *)&buf, strlen(buf.mtext)+1, 0);
} return 0;
}

接收端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> struct msgbuf {
long mtype;
char mtext[50];
}; int main()
{
int key, msg_id;
static struct msgbuf buf; key = ftok(".", 1); msg_id = msgget(key, IPC_CREAT | 0600); /* 设置消息类型 */
buf.mtype = 1; while(1){ /* 从消息队列接收消息 */
msgrcv(msg_id, (void*)&buf, sizeof(buf), buf.mtype, 0); printf("Recv msg : %s \n", buf.mtext);
} return 0;
}

运行结果:

删除消息队列:

ipcrm -q msqid

Linux进程间通信(System V) --- 消息队列的更多相关文章

  1. 进程间通信 System V 消息队列

    1.msgget (key_t ket,int flag) ; //创建一个新的消息队列或者访问一个已存在的消息队列 2.msgsnd(int msid, const void *ptr ,size_ ...

  2. Linux IPC System V 消息队列

    模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...

  3. Linux进程通信之System V消息队列

    System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的 ...

  4. linux c编程:System V消息队列一

    消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识.具有足 够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息.在某个进 ...

  5. linux网络编程之system v消息队列(二)

    今天继续学习system v消息队列,主要是学习两个函数的使用,开始进入正题: 下面则开始用代码来使用一下该发送函数: 在运行之前,先查看一下1234消息队列是否已经创建: 用上次编写的查看消息队列状 ...

  6. 第6章 System V消息队列

    6.1 概述 System V消息队列在内核中是list存放的,头结点中有2个指针msg_first 和msg_last.其中每个节点包含:下个节点地址的指针.类型.长度.数据等. 6.2 函数 6. ...

  7. 利用System V消息队列实现回射客户/服务器

    一.介绍 在学习UNIX网络编程 卷1时,我们当时可以利用Socket套接字来实现回射客户/服务器程序,但是Socket编程是存在一些不足的,例如: 1. 服务器必须启动之时,客户端才能连上服务端,并 ...

  8. UNIX环境高级编程——system V消息队列

    unix早期通信机制中的信号能够传送的信息量有限,管道则只能传送无格式字节流,这远远是不够的.     消息队列(也叫报文队列)客服了这些缺点:     消息队列就是一个消息的链表.     可以把消 ...

  9. Linux 进程间通信(posix消息队列 简单)实例

    Linux 进程间通信(posix消息队列 简单)实例 详情见: http://www.linuxidc.com/Linux/2011-10/44828.htm 编译: gcc -o consumer ...

随机推荐

  1. 【Node.js】安装及使用

    Node.js是在Chrome的V8 JavaScript引擎上构建的JavaScript运行时.Node.js使用事件驱动的非阻塞I / O模型,使其轻量且高效.Node.js的软件包生态系统npm ...

  2. To handling editor letter

    一般崔稿信写法: Dear Editor: Sorry for disturbing you. We’re not sure if it is the right time to contact yo ...

  3. TJOI2018 简要题解

    数学计算 用线段树记录之前乘过的每一个数,作除法时把原本的乘数改成111即可. 代码: #include<bits/stdc++.h> #define lc (p<<1) #d ...

  4. Codeforces Round #546 (Div. 2) E 推公式 + 线段树

    https://codeforces.com/contest/1136/problem/E 题意 给你一个有n个数字的a数组,一个有n-1个数字的k数组,两种操作: 1.将a[i]+x,假如a[i]+ ...

  5. docker-compose安装redis-sentinel集群(1主+2副+2哨兵)

    前提:本试验环境已经提前安装了docker和docker-compose 说明:本次部署是单机伪集群,想要部署真正的集群,需要将秒个主件拆分到各个机器上去部署,只修改ip地址 1.下载redis的相关 ...

  6. python运算符优先级

    下面这个表给出Python的运算符优先级,从最低的优先级(最松散地结合)到最高的优先级(最紧密地结合).这意味着在一个表达式中,Python会首先计算表中较下面的运算符,然后在计算列在表上部的运算符. ...

  7. POI SXSSFWorkbook 读取模板 存在公式解决

    package com.baoqilai.base.service.export; import java.io.File; import java.io.FileInputStream; impor ...

  8. JS 的execCommand 方法 做的一个简单富文本

    execCommand 当一个 HTML 文档切换到设计模式(designMode)时,文档对象暴露 execCommand 方法,该方法允许运行命令来操纵可编辑区域的内容.大多数命令影响文档的选择( ...

  9. 小程序json字符串转为对象

    小程序里json字符串转为对象使用JSON.parse()方法转变无效, 看报错提示有单引号“ ' ” 因为单引号而无效, 将单引号全改双引号即可. 报错如下: VM11050:1 thirdScri ...

  10. 第二节——vue多页面开发

    我们平常用vue开发的时候总觉得vue好像就是专门为了单页面应用而诞生的,其实不是.因为vue在工程化开发的时候很依赖webpack,而webpack是将所有的资源整合到一块,弄成一个单页面. 但是v ...