消息的基本属性

System V的消息属性包含在一个msqid_ds的结构中

struct msqid_ds{
struct ipc_cerm msg_perm; //读取权限, 0644, 0777
struct *msg_first; //消息队列的第一条消息地址
struct *msg_last; //消息队列的最后一条消息地址
msglen_t msg_cbytes; //当前消息的长度
msgnum_t msg_qnum; //消息队列中的消息总数
msglen_t msg_qbytes; //一条消息的最大长度
pid_t msg_lspid; //last sender进程ID
pid_t msg_lrpid; //last receiver进程ID
time_t msg_stime; //time of last msgsnd()
time_t msg_rtime; //time of last msgrcv()
time_t msg_ctime; //time of last msgctl()
};

消息格式:

由一个结构组成,第一个long参数类型表示消息类型(怎么解读消息由用户自己定义与系统无关), 且其值必须大于0; 第二个为消息内容, 其长度和数据类型可自定义; 除第一个结构成员固定外, 其它成员的数量也可以自定义

struct msgbuf{
long mtype;
char mtext[1];
}

基本函数:

#include <sys/ipc.h>
key_t ftok(char *fname, int id); #include <sys/msg.h>
int msgget(key_t key, int oflag);
int msgsnd(int msgqid, const void *ptr, size_t length, int flag);
ssize_t msgrcv(int msqid, void *ptr, size_t length, long type, int flag);
int msgctl(int msqid, int cmd, struct msqid_ds *buff);

ftok函数:用于生成一个唯一的key_t, fname为一个已存在的文件名, id取0-255之间的正整数. 实际是通过获取文件的i节点号再加上id形成唯一的key_t.

msgget函数:key_t可以为IPC_PRIVATE生成随机数; oflag可以是0644|IPC_CREAT|IPC_EXCL的组合

msgsnd函数:前三个参数同write函数, flag为0或IPC_NOWAIT设定是否等待

msgrcv函数:前三个参数同read函数,flag参数同msgsnd

type=0时按顺序取出第一条消息

type>0时取出消息队列中type为其值的第一条消息

type<0时取绝对值范围内type最小的第一条消息

msgctl函数:

cmd=IPC_RMID时,删除指定的msqid消息队列,第三个参数无意义

cmd=IPC_SET时,用第三个参数来代替当前消息队列属性

cmd=IPC_STAT,获取msqid消息队列的属性,通过第三个参数返回

包裹函数

vmqpack.h

#ifndef _VMQPACK_H
#define _VMQPACK_H #include "unpipc.h"
#include <sys/types.h>
#include <sys/msg.h> struct msgbuf{
long mtype;
char mtext[100];
}; key_t Ftok(char *fname,int id);
int Msgget(key_t key,int oflag);
void Msgsnd(int mqid,const void *ptr,size_t length, int flag);
ssize_t Msgrcv(int msqid, void *ptr, size_t length, long type, int flag);
void Msgctl(int msqid, int cmd, struct msqid_ds *buff); #endif

vmqpack.c

#include "vmqpack.h"

key_t Ftok(char *fname,int id){
key_t key=ftok(fname,id);
if(key == -1)
err_quit("ftok error");
return key;
}
int Msgget(key_t key,int oflag){
int mqid=msgget(key,oflag);
if(mqid == -1)
err_quit("msgget errror");
return mqid;
}
void Msgsnd(int mqid, const void *ptr, size_t length, int flag){
if(msgsnd(mqid,ptr,length,flag) == -1)
err_quit("msgsnd error");
}
ssize_t Msgrcv(int msqid, void *ptr, size_t length, long type, int flag ){
ssize_t n=msgrcv(msqid,ptr,length,type,flag);
if(n == -1)
err_quit("msgrcv error");
return n;
}
void Msgctl(int msqid, int cmd, struct msqid_ds *buff){
int ret=msgctl(msqid,cmd,buff);
if(ret == -1)
err_quit("msgctl error");
}

发送与接收

send.c

#include "vmqpack.h"

int main(int argc, char *argv[]){
int mqid;
long type;
struct msgbuf buf;
if(argc != 3)
err_quit("usage: send <pathname> <type>");
type=atoi(argv[2]);
mqid=Msgget(ftok(argv[1],0),0644|IPC_CREAT);
buf.mtype=type;
strncpy(buf.mtext,"hello, server",strlen("hello,server")+1);
Msgsnd(mqid,&buf,sizeof(buf),0);
exit(0);
}

recv.c

#include "vmqpack.h"
int main(int argc, char *argv[]){
int c,flag,mqid;
long type;
ssize_t n;
struct msgbuf buff;
key_t key;
type=flag=0;
while((c=getopt(argc,argv,"nt:")) != -1){
switch(c){
case 'n':
flag |= IPC_NOWAIT;
break;
case 't':
type=atol(optarg);
break;
}
}
if(optind != argc -1)
err_quit("usage: recv[-n] [-t type] <pathname>");
key=Ftok(argv[optind],0);
mqid=Msgget(key,0400);
n=Msgrcv(mqid,&buff,sizeof(buff),type,flag);
printf("read %d bytes, type=%ld\n",n,buff.mtype);
printf("msgdata: %s\n",buff.mtext);
Msgctl(mqid,IPC_RMID,NULL);
exit(0);
}

System V消息队列的更多相关文章

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

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

  2. 第6章 System V消息队列

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

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

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

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

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

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

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

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

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

  7. 第二十五章 system v消息队列(一)

    IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...

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

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

  9. Linux IPC System V 消息队列

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

随机推荐

  1. Angularjs 使用filter格式化输出href

    工作中,由于是多级菜单,如果上级菜单为空,就会访问Angularjs 默认的state,然后再展开菜单,我找资料之后,才知道是通过filter来格式化输出数据的,格式是{{ expression | ...

  2. 如何在mac上安装composer(How to install composer on the Mac)

    Change into a directory in your path like cd /usr/local/bin Get Composer curl -sS https://getcompose ...

  3. Android Studio使用OpenCV后,使APP不安装OpenCV Manager即可运行

    转载自http://www.cnblogs.com/tail/p/4618790.html 采用静态初始化的方法,可以戳下边的链接查看官方的文档介绍 http://docs.opencv.org/do ...

  4. 十一、Android学习笔记_AsyncQueryHandler的应用

    研究AsyncQueryHandler这个类的时候遇到了几个重要的不清楚的知识点 1. Handler与Thread,Looper的关系 2. HandlerThread是干什么用的 3. Threa ...

  5. 解决discuz模板插入jvascript脚本问题(Unexpected token <)

    问题描述: 最近学习discuz中要做一个焦点图,添加一个模板,让其显示后台推送图片,其中模块模板中要用到如下的代码 <div class="wrap"> <di ...

  6. 使用命令修改ip地址

    简述:以serverv 2012 r2为例 常用的几种,当然不全,希望能较快的速率记下一种便可 直接配置 1.      查看网卡的显示名称 2.      配置静态iP地址 3.      查看配置 ...

  7. html5 拖曳功能的实现[转]

    HTML5中实现拖放操作,至少经过如下步骤1)设置被拖放对象元素的draggable属性设置为true2)编写与拖放有关的事件处理代码 事件 产生事件的元素 描述 dragstart 被拖拽物体 开始 ...

  8. 7款个性化jQuery/HTML5地图插件

    现在我们经常会用到一些地图应用,无论是在网页上还是手机App中,地图貌似是一个不可或缺的应用.本文将带领大家一起来看看一些基于jQuery和HTML5的个性化地图插件,有几款地图比较实用,有些则是具有 ...

  9. Jquery 学习一

    一.jQuery概述 1.Javascript代码库 在早期的项目开发中都是使用Javascript原生代码,一行一行编写.但是Javascript自身存在3个弊端: ① 复杂的DOM操作 ② 不一致 ...

  10. android ListView的怪异现象

    我们已经知道,当条目没显示一次,那个类重写的最后一个函数就执行一次,但是现在,发生了怪异现象!当窗体的属性设置为包裹的时候,会重复显示多次,所以,高度,宽度都要设置为充满类型才可以