详解linux进程间通信-消息队列
前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。
一、系统V IPC
三种系统V IPC:消息队列、信号量以及共享内存(共享存储器)之间有很多相似之处。
每个内核中的 I P C结构(消息队列、信号量或共享存储段)都用一个非负整数的标识符
( i d e n t i f i e r )加以引用。
无论何时创建I P C结构(调用m s g g e t、 s e m g e t或s h m g e t) ,都应指定一个关键字(k e y),关
键字的数据类型由系统规定为 k e y _ t,通常在头文件< s y s / t y p e s . h >中被规定为长整型。关键字由
内核变换成标识符。
以上简单介绍了IPC,对接下来介绍的消息队列、信号量和共享内存有助于理解。
二、消息队列
1、简介
消息队列是消息的链接表 ,存放在内核中并由消息队列标识符标识。我们将称消息队列为
“队列”,其标识符为“队列 I D”。 m s g g e t用于创建一个新队列或打开一个现存的队列。 m s g s n d
用于将新消息添加到队列尾端。每个消息包含一个正长整型类型字段,一个非负长度以及实际
数据字节(对应于长度),所有这些都在将消息添加到队列时,传送给 m s g s n d。 m s g r c v用于从
队列中取消息。我们并不一定要以先进先出次序取消息,也可以按消息的类型字段取消息。
2、函数介绍
- ftok函数
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);//“/home/linux” , 'a'
功能:生成一个key(键值)
- msgget函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:创建或取得一个消息队列对象
返回:消息队列对象的id 同一个key得到同一个对象
格式:msgget(key,flag|mode);
flag:可以是0或者IPC_CREAT(不存在就创建)
mode:同文件权限一样
- msgsnd函数
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:将msgp消息写入标识为msgid的消息队列
msgp:
struct msgbuf {
long mtype; /* message type, must be > 0 */消息的类型必须>0
char mtext[1]; /* message data */长度随意
};
msgsz:要发送的消息的大小 不包括消息的类型占用的4个字节
msgflg: 如果是0 当消息队列为满 msgsnd会阻塞
如果是IPC_NOWAIT 当消息队列为满时 不阻塞 立即返回
返回值:成功返回id 失败返回-1
- msgrcv函数
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:从标识符为msgid的消息队列里接收一个指定类型的消息 并 存储于msgp中 读取后 把消息从消息队列中删除
msgtyp:为 0 表示无论什么类型 都可以接收
msgp:存放消息的结构体
msgsz:要接收的消息的大小 不包含消息类型占用的4字节
msgflg:如果是0 标识如果没有指定类型的消息 就一直等待
如果是IPC_NOWAIT 则表示不等待
- msgctl函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgid,IPC_RMID,NULL);//删除消息队列对象
程序2-2将简单演示消息队列:
--- snd.c ---
#include "my.h" typedef struct{
long type;
char name[];
int age;
}Msg; int main()
{
key_t key = ftok("/home/liudw",'');
printf("key:%x\n",key); int msgid = msgget(key,IPC_CREAT|O_WRONLY|);
if(msgid<)
{
perror("msgget error!");
exit(-);
} Msg m;
puts("please input your type name age:");
scanf("%ld%s%d",&m.type,m.name,&m.age);
msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),); return ;
}
--- rcv.c ---
#include "my.h" typedef struct{
long type;
char name[];
int age;
}Msg; int main()
{
key_t key = ftok("/home/liudw",'');
printf("key:%x\n",key); int msgid = msgget(key,O_RDONLY);
if(msgid<)
{
perror("msgget error!");
exit(-);
} Msg rcv;
long type;
puts("please input type you want!");
scanf("%ld",&type); msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,);
printf("rcv--name:%s age:%d\n",rcv.name,rcv.age); msgctl(msgid,IPC_RMID,NULL);
return ;
}
运行演示:
三、详解ftok函数
- ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。
- 该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
- proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;
为了验证以上观点,对程序2-2稍作修改,将路径和proj_id修改:
程序3-1如下:
--- snd.c ---
#include "my.h" typedef struct{
long type;
char name[];
int age;
}Msg; int main()
{
key_t key = ftok("/home",'a');
printf("key:%x\n",key); int msgid = msgget(key,IPC_CREAT|O_WRONLY|);
if(msgid<)
{
perror("msgget error!");
exit(-);
} Msg m;
puts("please input your type name age:");
scanf("%ld%s%d",&m.type,m.name,&m.age);
msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),); return ;
}
--- rcv.c ---
#include "my.h" typedef struct{
long type;
char name[];
int age;
}Msg; int main()
{
key_t key = ftok("/home",'a');
printf("key:%x\n",key); int msgid = msgget(key,O_RDONLY);
if(msgid<)
{
perror("msgget error!");
exit(-);
} Msg rcv;
long type;
puts("please input type you want!");
scanf("%ld",&type); msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,);
printf("rcv--name:%s age:%d\n",rcv.name,rcv.age); msgctl(msgid,IPC_RMID,NULL);
return ;
}
运行演示如下图:
总结:主要介绍了进程间通信的消息队列,有疑问可以留言,一定即时解答。
详解linux进程间通信-消息队列的更多相关文章
- 详解linux进程间通信-信号
前言:之前说看<C++ Primer >暂时搁浅一下,迷上公司大神写的代码,想要明白,主要是socket.进程间通信! 知道进程间通信:信号.信号量.管道.消息队列.共享内存(共享存储), ...
- Linux进程间通信-消息队列(mqueue)
前面两篇文章分解介绍了匿名管道和命名管道方式的进程间通信,本文将介绍Linux消息队列(posix)的通信机制和特点. 1.消息队列 消息队列的实现分为两种,一种为System V的消息队列,一种是P ...
- ActiveMQ基本详解与总结& 消息队列-推/拉模式学习 & ActiveMQ及JMS学习
转自:https://www.cnblogs.com/Survivalist/p/8094069.html ActiveMQ基本详解与总结 基本使用可以参考https://www.cnblogs.co ...
- Linux进程间通信—消息队列
四.消息队列(Message Queue) 消息队列就是消息的一个链表,它允许一个或者多个进程向它写消息,一个或多个进程向它读消息.Linux维护了一个消息队列向量表:msgque,来表示系统中所有的 ...
- linux进程间通信-消息队列
一 消息队列的介绍 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构. 我们可以通过发送消息来避免命名管道的 ...
- Linux 进程间通信 消息队列 实现两个进程间通信
例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据 文件1 创建进程1 终端输入通过消息队列发送数据 #include <stdio ...
- linux进程间通信消息队列:msgsnd: Invalid argument
今天写了个消息队列的小测试程序结果send端程序总是出现:msgsnd: Invalid argument,搞了半个小时也没搞明白,后来查资料发现我将(st_msg_buf.msg_type = 0; ...
- Linux 进程间通信 消息队列
1.特点: 消息队列是IPC对象的一种 消息队列由消息队列ID来唯一标识 消息队列就是一个消息的列表.用户可以在消息队列中添加消息.读取消息等. 消息队列可以按照类型来发送/接收消息(消息的类型是正整 ...
- 详解linux进程间通信-管道 popen函数 dup2函数
前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术-I P C(InterProcess Communication ...
随机推荐
- 学习TensorFlow,生成tensorflow输入输出的图像格式
TensorFLow能够识别的图像文件,可以通过numpy,使用tf.Variable或者tf.placeholder加载进tensorflow:也可以通过自带函数(tf.read)读取,当图像文件过 ...
- 【一天一道LeetCode】#225. Implement Stack using Queues
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Impleme ...
- 07 设置View的显示与隐藏
在代码中: 例子: <span style="font-size:14px;">ImageButton imageButton = new ImageButton(th ...
- Java数据类型及类型转换
http://blog.csdn.net/pipisorry/article/details/51290064 java浮点数保留n位小数 import java.text.DecimalFormat ...
- input事件--->按键事件的基本实现
本程序基于TINY4412开发板,程序已经验证过,完全正确: 那么,如何来写这样的一个驱动程序呢? 1.分配一个input_dev结构体 2.设置 3.注册 4.硬件相关的代码,比如中断,定时器,休眠 ...
- Android初级教程Activity小案例(计算器乘法运算)
首先设置两个布局文件,一个布局文件进行输入数据,获取加法运算:另一个布局文件进行显示最终结果.Activity1启动Activity2,并传递计算结果值给Activity2. main.xml: &l ...
- Java进阶(三十一) Web服务调用
Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...
- Mybatis执行Executor(一)
在DefaultSqlSession中我们可以看到一系列的增删改查操作的其实都是在调用Executor的接口,Mybatis对外统一提供了一个操作接口类Executor,提供的接口方法有update. ...
- 《java入门第一季》之泛型类引入
首先用一个例子引入泛型类. 我定义一个Object类: package cn.it_03; public class ObjectTool { private Object obj; public O ...
- 【Unity技巧】调整画质(贴图)质量
写在前面 当我们在Unity中,使用图片进行2D显示时,会发现显示出来的画面有明显的模糊或者锯齿,但是美术给的原图却十分清晰. 要改善这一状况实际上很简单. 造成这样的原因,是Unity在导入图片(或 ...