热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux进程间消息队列持久化,详解linux进程间通信消息队列

前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。一、系统VIPC三种系统VIPC:消息队列、信号量以及共享内存(共享存储

前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。

一、系统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,通常在头文件中被规定为长整型。关键字由

内核变换成标识符。

以上简单介绍了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

#include

key_t ftok(const char *pathname, int proj_id);//“/home/linux” , 'a'

功能:生成一个key(键值)

msgget函数

#include

#include

#include

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[20];

int age;

}Msg;

int main()

{

key_t key = ftok("/home/liudw",'6');

printf("key:%x\n",key);

int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);

if(msgid<0)

{

perror("msgget error!");

exit(-1);

}

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),0);

return 0;

}

---  rcv.c  ---

#include "my.h"

typedef struct{

long type;

char name[20];

int age;

}Msg;

int main()

{

key_t key &#61; ftok("/home/liudw",&#39;6&#39;);

printf("key:%x\n",key);

int msgid &#61; msgget(key,O_RDONLY);

if(msgid<0)

{

perror("msgget error!");

exit(-1);

}

Msg rcv;

long type;

puts("please input type you want!");

scanf("%ld",&type);

msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);

printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

msgctl(msgid,IPC_RMID,NULL);

return 0;

}

运行演示&#xff1a;

55f3935ad710f1305dc0ea341524e814.png

cc21366e0d83765f4e8ead49703b57a3.png

三、详解ftok函数

ftok根据路径名&#xff0c;提取文件信息&#xff0c;再根据这些文件信息及project ID合成key&#xff0c;该路径可以随便设置。

该路径是必须存在的&#xff0c;ftok只是根据文件inode在系统内的唯一性来取一个数值&#xff0c;和文件的权限无关。

proj_id是可以根据自己的约定&#xff0c;随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;

为了验证以上观点&#xff0c;对程序2-2稍作修改&#xff0c;将路径和proj_id修改&#xff1a;

程序3-1如下&#xff1a;

---  snd.c  ---

#include "my.h"

typedef struct{

long type;

char name[20];

int age;

}Msg;

int main()

{

key_t key &#61; ftok("/home",&#39;a&#39;);

printf("key:%x\n",key);

int msgid &#61; msgget(key,IPC_CREAT|O_WRONLY|0777);

if(msgid<0)

{

perror("msgget error!");

exit(-1);

}

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),0);

return 0;

}

---  rcv.c  ---

#include "my.h"

typedef struct{

long type;

char name[20];

int age;

}Msg;

int main()

{

key_t key &#61; ftok("/home",&#39;a&#39;);

printf("key:%x\n",key);

int msgid &#61; msgget(key,O_RDONLY);

if(msgid<0)

{

perror("msgget error!");

exit(-1);

}

Msg rcv;

long type;

puts("please input type you want!");

scanf("%ld",&type);

msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);

printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

msgctl(msgid,IPC_RMID,NULL);

return 0;

}

运行演示如下图&#xff1a;

8cd7277deb580efd160e2c93fc080587.png 

4a85c091f68c5ea2c9ea787663b02eab.png

总结&#xff1a;主要介绍了进程间通信的消息队列&#xff0c;有疑问可以留言&#xff0c;一定即时解答。



推荐阅读
author-avatar
采蘑菇的灵的fans
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有