当前位置: 首页 > 编程日记 > 正文

linux进程间通信:system V消息队列

文章目录

      • 基本介绍
      • 编程接口
      • 代码实例
        • 消息队列的发送和接收
        • 消息队列中的消息对象的属性控制

基本介绍

  1. 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理。
  2. 进程之间的通信角色为:发送者和接受者
    发送者:
    a. 获取消息队列的ID(key或者msgid)
    b. 将数据放入一个带有标识的消息结构体,发送到消息队列
    接受者:
    a. 获取消息队列的ID
    b. 指定标识的消息从消息队列中读出,然后进一步后续处理
  3. 支持不同的进程标记不同的消息类型(1,2,3…),并由内核态维护对应消息类型的链表。
  4. 内核态的0号消息类型维护了一个链表,用来保存按照时间顺序加入的消息

编程接口

  1. 生成ipc对象的唯一标识key的接口
    a. 头文件 <sys/ipc.h>
    b. 函数声明 key_t ftok(const char *path, int id);
    c. 参数描述
    path需指定一个已经存在的可访问的文件
    id为用户可自由指定的id

  2. 创建或者打开一个消息队列,并获取system V 消息队列中消息的身份标识
    a. 头文件 <sys/types.h> <sys/ipc.h> <sys/msg.h>
    b. 函数声明 int msgget (ket_t key, int msgflg)
    c. 参数描述
    key 为ipc对象的唯一标识,生成的消息身份标识与该参数相关
    msgflg当该函数没有搜索到系统中与key值对应的消息队列,则msgflg会指定IPC_CREAT,创建一个队列,并返回消息标识
    d. 返回值:成功返回消息身份标识,失败返回-1

  3. 发送消息到消息队列
    a. 头文件 <sys/types.h> <sys/ipc.h> <sys/msg.h>
    b. 函数声明 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    c. 参数描述
    msqid 消息标识,类似于文件描述符fd
    msgp 消息内容指针
    msgsz 消息大小
    msgflg 当出现消息队列没有足够的可用空间时,可以通过设置msgflg为IPC_NOWAIT来让发送函数不产生阻塞,返回失败
    d. 返回值 失败返回-1,以及对应失败码;成功则返回0

  4. 从消息队列中接收消息
    a. 头文件 <sys/types.h> <sys/ipc.h> <sys/msg.h>
    b. 函数声明 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
    c. 参数描述
    msqid 消息标识,类似于文件描述符fd
    msgp 消息内容指针
    msgsz 消息大小,同时也是当前接收的消息最大能够接收的大小
    msgflg 当出现实际的消息内容大于设定的msgsz,可以通过MSG_NOERROR来将消息裁剪为msgsz大小进行获取,否则会返回失败。而消息仍然存在于消息队列。
    msgtyp 如果是0,则会读取处于消息队列的第一个消息;大于0,则会读取对应type处于消息队列中的第一个消息;如果小于0,则会读取type绝对值或者小于绝对值的消息队列的第一个消息。
    d. 返回值 失败返回-1,成功返回对应消息的大小

  5. 控制消息队列的各个操作
    a. 头文件 <sys/types.h> <sys/ipc.h> <sys/msg.h>
    b. 函数声明 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    c. 参数描述
    msgqid 消息标识
    cmd 针对消息标识的操作,合法的操作如下:

    • IPC_STAT 获取msgqid的消息对象的信息,将各个属性从内核拷贝到一个临时的数据结构msgqid_ds类型的buf;调用者需要对消息队列有读权限
    • IPC_SET 自己可以通过临时的msgqid_ds来设置内核中消息的对应msgqid_ds的属性
    • IPC_RMID 立即移除消息队列;当前调用者需要拥有 消息队列的所有者权限,或者高于所有者的权限(root)
    • IPC_INFO 返回消息队列的参数限制

    其他标识可以通过man msgctl来查看

代码实例

消息队列的发送和接收

发送端msg_snd.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define MSG_TYPE1 1
#define MSG_TYPE2 2 struct msgbuf
{long mtype;char mtext[100];
};int main()
{//当多用户的时候通过指定文件以及设置id来获取唯一的key标识//key_t key = ftok(".",100);key_t key = 12345; //个人使用的时候可以直接指定key//创建msg_qid的对象int msg_qid = msgget(key, IPC_CREAT | 0666);struct msgbuf msg;memset(&msg, 0 , sizeof(msg));//初始化消息类型以及消息内容msg.mtype = MSG_TYPE2;strncpy(msg.mtext, "hello world" , 80);//发送消息到消息标识的msg_qid IPC 对象中if( -1 == msgsnd(msg_qid,(void *)&msg,strlen(msg.mtext),0)) {printf("send msg failed\n");_exit(-1);}return 0;
}

编译运行:
gcc msg_snd.c -o msg_snd

运行前查看系统消息队列
ipcs -q

[root@node1 ~]# ipcs -q------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x000004d2 0          root       666        0            0

运行后,可以看到我们发送了消息队列的各个属性信息。关于key值,它为我们设置的12345的16进制数值

[root@node1 ~]# ./msg_snd 
[root@node1 ~]# ipcs -q------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x000004d2 0          root       666        0            0           
0x00003039 65538      root       666        11           1

接收端msg_rcv.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define MSG_TYPE1 1
#define MSG_TYPE2 2 struct msgbuf
{long mtype;char mtext[100];
};int main()
{key_t key = 12345;int msg_qid = msgget(key, IPC_CREAT | 0666);struct msgbuf msg;memset(&msg, 0 , sizeof(msg));if (-1 == msgrcv(msg_qid,(void *)&msg,sizeof(msg.mtext),MSG_TYPE2,0)) {printf("receive msg failed\n");_exit(-1);}printf("%s\n",msg.mtext);//当完成接收之后从消息队列中删除当前消息//msgctl(msg_id,IPC_RMID,NULL);return 0;
}

编译运行,可以看到已经接手到了我们之前发送的内容:

[root@node1 ~]# gcc msg_rcv.c -o msg_rcv
[root@node1 ~]# ./msg_rcv
hello world

查看消息队列情况,消息队列中的数据已经被接收,所以在used-bytes和messages中看不到消息内容了,但是没有删除该消息队列,所以消息标识仍然存在。我们可以在上述代码中加入msgctl

[root@node1 ~]# ipcs -q------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x000004d2 0          root       666        0            0                    
0x00003039 65538      root       666        0            0  

消息队列中的消息对象的属性控制

控制代码msg_ctl.c
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
其中主要控制的是消息队列一个数据结构,可以通过man msgctl查看 msqid_ds结构体

           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 inqueue (nonstandard) */msgqnum_t       msg_qnum;     /* Current number of messagesin queue */msglen_t        msg_qbytes;   /* Maximum number of bytesallowed in queue */pid_t           msg_lspid;    /* PID of last msgsnd(2) */pid_t           msg_lrpid;    /* PID of last msgrcv(2) */};

以下代码为主要控制参数的代码,通过msgctl的cmd参数进程控制

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int main()
{key_t key = 12345;int msg_id = msgget(key,IPC_CREAT|0666);struct msqid_ds info;//第一次先从已存在的12345的消息中获取队列状态if (-1 == msgctl(msg_id,IPC_STAT,&info)) {printf("control msg failed\n");_exit(-1);}//打印各个状态信息printf("uid :%d,gid:%d,cuid:%d,cgid:%d\n",\info.msg_perm.uid,info.msg_perm.gid,info.msg_perm.cuid,info.msg_perm.cgid);printf("mode:%o3o,cbytes:%lu,qnum:%lu,qbytes:%lu\n",\info.msg_perm.mode & 0777,info.__msg_cbytes,info.msg_qnum,info.msg_qbytes);//尝试设置消息队列允许的最大字节内容info.msg_qbytes = 16000;//通过cmd为IPS_SET的标记进行设置if (-1 == msgctl(msg_id, IPC_SET, &info)) {printf("ipc_set failed\n");_exit(-1);}if (-1 == msgctl(msg_id, IPC_STAT, &info)) {printf("ipc_stat failed\n");_exit(-1);}printf("mode:%o3o,cbytes:%lu,qnum:%lu,qbytes:%lu\n",\info.msg_perm.mode & 0777,info.__msg_cbytes,info.msg_qnum,info.msg_qbytes);return 0;
}

输出如下,可以看到我们控制的队列允许的最大字节内容msg_qbytes已经设置进去:

[root@node1 ~]# ./msg_ctl 
uid :0,gid:0,cuid:0,cgid:0
mode:6663o,cbytes:11,qnum:1,qbytes:16000
mode:6663o,cbytes:11,qnum:1,qbytes:16000

相关文章:

将一个一维数组转化为二进制表示矩阵。例如_算法之矩阵最大区域问题

例如&#xff1a;给定一个m*m(0<n)的矩阵&#xff0c;请找到此矩阵的一个子矩阵&#xff0c;并且此子矩阵的各个元素的和最大&#xff0c;输出这个最大的值。或者给出一个柱形矩阵求最大子矩阵的最大值。首先我们需要了解一下最大字段和问题。最大子段和问题给定一个长度为n…

伪元素first-letter

用于设置一个块级元素首位字符的样式&#xff0c;而且仅对该字符设置样式 p&#xff1a;first-letter{ font-size&#xff1a;200%}是让P中的第一个字符是其他字符大小的两倍转载于:https://www.cnblogs.com/damade/p/3518583.html

fedora17 的 rc.local

Fedora17上已经找不到/etc/rc.local了&#xff0c;如果我们想开机执行某个脚本&#xff0c;就需要手动创建这个文件&#xff0c;目录也发生了小小变化&#xff1a; 1. 新建文件/etc/rc.d/rc.local&#xff0c;第一行须指明执行shell&#xff1a; [root www.linuxidc.com rc.d]#…

使用TortoiseGit,设置ssh方式连接git仓库。

开始设置之前的准备&#xff1a;建立项目文件夹&#xff0c;初始化git仓库(右键 git init)&#xff0c;右键打开 git bash &#xff0c;git pull “仓库地址”, 把网站上的仓库代码拉取下来。 TortoiseGit使用扩展名为ppk的密钥&#xff0c;而不是ssh-keygen生成的rsa密钥。 也…

linux进程间通信:消息队列实现双端通信

双端通信描述 利用消息队列针对发送接受消息的类型唯一性 进行多个客户端之间消息传递&#xff0c;而不需要server端进行消息转发。 同时消息队列的读阻塞和写阻塞特性&#xff08;消息队列中已经写入数据&#xff0c;如果再不读出来&#xff0c;则无法再次写入&#xff09;让…

windows 软件安装事件_苹果安装windows,报windows支持软件未能存储到所选驱动器

今天去给一个IT外包客户维修电脑&#xff0c;前台的一台苹果电脑需要安装双系统&#xff0c;苹果电脑安装双系统对我们专业安装系统工程师来说&#xff0c;这不是很简单的嘛&#xff01;客户问需要多长时间&#xff0c;信心满的说一到两个小时&#xff01;客户说那你开始弄吧。…

C# Attribute简介

一 、EventAttribute有&#xff1a; BrowsableAttribute 、CategoryAttribute、DescriptionAttribute、DefaultEventAttribute PropertyAttribute有&#xff1a; BrowsableAttribute 、CategoryAttribute、DescriptionAttribute、 DefaultPropertyAttribute、DefaultValueAttri…

P2P之UDP穿透NAT的原理

关键词: P2P UDP NAT 原理 穿透 Traveral Symmetric Cone原始作者: Hwycheng Leo(FlashBTHotmail.com)源码下载: http://bbs.hwysoft.com/download/UDP-NAT-LEO.rar参考&#xff1a;http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt P2P之UDP穿透NAT的原理…

快速幂运算and 快速乘运算

ll qpow(ll a,ll b) {ll ans1;while(b){if(b&1) ans(ans*a)%mod;a(a*a)%mod;b>>1;}return ans; } 快速乘运算 ll mult(ll a,ll b,ll mod) {a%mod,b%mod;ll sa,sum0;while(b){if (b&1){sums;if (sum>mod)sum-mod;}b>>1;s<<1;if (s>mod)s-mod;}r…

linux进程间通信:system V 共享内存

文章目录思维导图如下通信原理优势运行流程编程接口编程实例思维导图如下 通信原理 多个进程共享物理内存的同一块区域&#xff08;通常称之为“段”:segment&#xff09;抛弃了内核态消息转存处理的过程&#xff0c;让两个进程直接通过一块内存进行通信 我们普通的像PIPE,FI…

python函数手册68_直接在python中检索68个内置函数?

Python 3.5中的一种方法是列出具有__module__属性的对象,并将其设置为builtins和lowercase name&#xff1a;>>> sorted(k for k, v in vars(__builtins__).items()if k.islower() and getattr(v, __module__, ) builtins)[__build_class__, __import__, abs, all, a…

《深入理解Java虚拟机》笔记3

垃圾收集算法 (1)标记清除 根据根搜索确定对象是否已死&#xff0c;已死对象标记&#xff0c;然后一起清除。 这个其实不算什么算法&#xff0c;最正常想法应该就是这样。但是&#xff0c;缺点 是效率不高&#xff0c;如果有很多不连续的小对象需要回收&#xff0c;会花好多时间…

Step-By-Step在AIX上安装Oracle RAC

最近遇到一个项目&#xff0c;是在AIX5.3上安装ORACLE 9i RAC&#xff0c;说实话&#xff0c;ORACLE俺压根就没有接触过&#xff0c;我也是临危受命。感觉如同当年实施AS400的XSM项目一般。无奈&#xff0c;下载了N多本REDBOOK开始研究&#xff0c;终于有了些眉目&#xff0c;找…

Python中输出字体的颜色设置

1.实现过程 终端的字符颜色是用转义序列控制的&#xff0c;是文本模式下的系统显示功能&#xff0c;和具体的语言无关。控制字符颜色的转义序列是以ESC开头,即用\033来完成 2.书写过程开头部分: \033[显示方式;前景色;背景色m结尾部分: \033[0m注意&#xff1a;开头部分的三个…

linux进程间通信:system V 信号量

文章目录概念描述通信原理编程接口使用流程编程案例概念描述 英文&#xff1a;semaphore 简称SEM&#xff0c;主要用来进行进程间同步本质&#xff1a;内核维护的一个正整数&#xff0c;可对其进行各种/-操作分类&#xff1a;systemV 信号量、POSIX 有名信号量、POSIX 无名信号…

设计模式总结1

1.代码不是没有错误就是最好的 &#xff08;1&#xff09;命名要规范-------取一个好的名字。 &#xff08;2&#xff09;代码少做无用功。 &#xff08;3&#xff09;注意逻辑错误。 &#xff08;4&#xff09;面向对象&#xff1a;可维护、可复用、可扩展、灵活性好。 2.简单…

mysql 单选字段_mysql字段类型

学习自 https://www.cnblogs.com/jennyyin/p/7895010.html&#xff0c;感谢原博主的奉献mysql支持多种类型&#xff0c;大致可以分为三类&#xff1a;数值、字符串、日期/时间。数值类型类型大小范围(有符号)范围(无符号)用途tinyint1字节(-128, 127)(0,255)小整数值smallint2字…

ios时间差,以时间格式显示

为什么80%的码农都做不了架构师&#xff1f;>>> NSDate *nowDate [[NSDate alloc]init]; double diffTime [nowDate timeIntervalSinceDate:preDate]; int diffHour diffTime / (60*60); int diffMin ( diffTime - diffHour*(60*60) ) / (60); int diffSec…

深入理解C++中public、protected及private用法

深入理解C中public、protected及private用法 这篇文章主要介绍了C中public、protected及private用法,对于C面向对象程序设计来说是非常重要的概念,需要的朋友可以参考下初学C的朋友经常在类中看到public&#xff0c;protected&#xff0c;private以及它们在继承中表示的一些访问…

v-vim 代码批量缩进,字符串精确查找及替换

vim中代码批量缩进 有如下两种办法&#xff0c;主要依靠>和<字符来进行 缩进的单位通过设置~/.vimrc,添加如下行 set tabstop4 "设定tab宽度为4个字符 set shiftwidth4 "设定自动缩进为4个字符 set expandtab "用space替代tab的输入 set noexpandtab &q…

Codeforces Round #228 (Div. 1)B

进制构造 这里用了十进制 有点像串并联 每一位代表的数分开表示出来再把每一位的数并起来 比如892 就是800902 800又可分为8*10*10。。。 1 #include <iostream>2 #include<cstdio>3 #include<cstring>4 #include<algorithm>5 #include<stdlib.h&g…

javaweb实现mysql备份功能_java web 实现mysql 数据库备份、恢复

如题&#xff0c;由于项目需要&#xff0c;研究并实现了java web的 mysql数据库的备份、下载、恢复功能&#xff0c;中间遇到一些问题&#xff0c;耗费了不少时间&#xff0c;下面让我一一道来&#xff1a;背景介绍&#xff1a;window 7系统mysql 5.7eclipsespring mvctomcat 7…

在windows8 上安装framework 3.5

在电脑上装了windows8 的双系统后&#xff0c;为了装上Windows Live Writer&#xff0c;需要安装framework3.5.在线安装等了很久都装不上&#xff0c;下载的安装包不能用&#xff0c;提示需要framework3.5的支持。死循环啊 。搜索找到离线更新的方法&#xff0c; 离线更新方法&…

C#第一章笔记

第一个C#程序 namespace 是C#中组织代码的方式&#xff0c;它的作用那个类似java中的包 using 在Java中作用如果导入其他包 应该是用import关键字而在C#中应使用using关键字来引用 class关键字 与java一样C#也是一门面向对象的得语言&#xff0c;使用class关键字来表示类 Main&…

linux进程间通信:system V 信号量和共享内存实现进程间同步

关于信号量和共享内存的相关描述已经在前几篇提到过&#xff1b; 信号量&#xff1a;即内核维护的一个正整数&#xff0c;可以使用内核提供的p/v接口进行该正整数的/-操作&#xff0c;它主要用来表示系统中可用资源的个数&#xff0c;协调各个进程有序访问资源&#xff0c;防止…

mysql三次握手_一文彻底搞懂 TCP三次握手、四次挥手过程及原理

原创文章首发于公众号&#xff1a;「码农富哥」&#xff0c;欢迎收藏和关注&#xff0c;如转载请注明出处&#xff01;TCP 协议简述TCP 提供面向有连接的通信传输&#xff0c;面向有连接是指在传送数据之前必须先建立连接&#xff0c;数据传送完成后要释放连接。无论哪一方向另…

【转】常见系统中文字体的英文名

http://www.aoao.org.cn/blog/2008/03/fonts-chinese/ http://www.yale.edu/chinesemac/pages/fonts.html Mac OS的一些&#xff1a; 华文细黑&#xff1a;STHeiti Light [STXihei]华文黑体&#xff1a;STHeiti华文楷体&#xff1a;STKaiti华文宋体&#xff1a;STSong华文仿宋&…

手动新增swap分区

1、建立1G的交换分区&#xff08;填充&#xff09; #dd if /dev/zore of /opt/swapfile bs1M count1024 2、设置交换分区文件 #mkswap /opt/swapfile 3、立即启用交换分区文件 #swapon /opt/swapfile 4、系统开机时自动挂载新分区 #vim /etc/fstab 末尾添加&#xff1a;/opt…

js捕获和冒泡

面向对象&#xff1a; 1.单例模式 2.工厂模式 3.构造函数 &#xff08;1&#xff0c;2&#xff0c;3的目的都是生成对象&#xff09; js天生自带的类 object&#xff08;基类&#xff09; 子类&#xff1a;function&#xff08;函数&#xff09; array&#xff08;数组&…

linux进程间通信:system V 信号量 生产者和消费者模型编程案例

生产者和消费者模型&#xff1a; 有若干个缓冲区&#xff0c;生产者不断向里填数据&#xff0c;消费者不断从中取数据两者不冲突的前提&#xff1a; 缓冲区有若干个&#xff0c;且是固定大小&#xff0c;生产者和消费者各有若干个生产者向缓冲区中填数据前需要判断缓冲区是否满…