进程间通信(IPC)(2)—— 消息队列

来源:互联网 发布:局域网管控软件 编辑:程序博客网 时间:2024/05/16 05:38

3.2 消息队列

  有一个队列,队列中存放各种消息。每个进程都可以把数据封存在消息中,再放入队列。
  每个进程都可以拿到消息队列,再从中取出/放入消息。
  消息队列不会产生覆盖问题,但需要考虑队列长度。

消息队列的编程步骤:
  1 生成key,使用ftok()或用头文件定义
  2 创建/获取消息队列 msgget()
  3 发送/接收消息 msgsnd() / msgrcv()
  4 如果不会再被使用(所有进程都不用)可以删除
    msgctl()

相关函数:
msgget()用法和shmget()基本一样。获取时flag为0,新建时flag为 权限|IPC_CREAT|IPC_EXCL
msgctl()用法和shmctl()基本一样。

int msgsnd(int msgid,void* p,size_t size,int flag)
msgid 就是消息队列,p是发送的消息的首地址,size是发送消息的大小,flag为0代表阻塞,为IPC_NOWAIT代表非阻塞。(消息满了以后是否等待)
成功返回0,失败返回-1

ssize_t msgrcv(int msgid,void* buf,size_t size,int msgtype,int flag)
msgid、flag和msgsnd()一样
buf是用来接收消息的首地址
size是sizeof(buf)
msgtype 代表消息的类型,消息分为:
  无类型消息和有类型消息。

3.2.1 无类型消息

msga.c#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/msg.h>int main(){    key_t key = ftok(".",100);    if(key==-1) perror("ftok"),exit(-1);    int msgid = msgget(key,        0666|IPC_CREAT|IPC_EXCL);    if(msgid==-1) perror("msgget"),exit(-1);    int res = msgsnd(msgid,"hello",5,0);    if(res==-1) perror("msgsnd"),exit(-1);    printf("send ok\n");}//练习:写msgb.c,从消息队列中取出hello并打印----------------------------------------------------------msgb.c#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/msg.h>int main(){    key_t key = ftok(".",100);    if(key==-1) perror("ftok"),exit(-1);    int msgid = msgget(key,0);    if(msgid==-1) perror("msgget"),exit(-1);    char buf[100] = {};    int res = msgrcv(msgid,buf,sizeof(buf),0,0);    if(res==-1) perror("msgrcv"),exit(-1);    printf("buf=%s,rcv=%d\n",buf,res);}

无类型消息可以是任意类型,比如:整数、字符串、浮点…
无类型消息的取出遵循队列的基本准则: FIFO。

3.2.2 有类型消息

有类型消息,类型必须是一个结构体:
  struct 自定义名字{
    long mtype;//消息类型,必须有,格式固定
    char msg[];//数据
  };
数据是:char数组,长度和名称可以自定义,用其他类型也可以
mtype取值时,必须 大于0。(赋值时不能<=0)
接收数据时可以按消息类型接收,msgrcv()中的第四个参数可以指定接收消息的类型:
= 0 代表接收任意类型的消息(遵循先入先出)
大于 0 代表接收特定类型的消息(mtype=值)
<0 代表接收类型小于等于参数绝对值的消息
  次序从小到大,如果类型相同,按在队列中的位置
  
有类型消息

有类型消息在计算发送和接收的size时,可以不计算类型所占的空间。(sizeof(struct)-4)。发送和接收要么都计算,要么都不计算。

msgtypea.c#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/msg.h>#include <string.h>struct mymsg{    long mtype; //类型    char buf[256];// 数据};int main(){    key_t key = ftok(".",100);    int msgid = msgget(key,0666|IPC_CREAT);    if(msgid==-1) perror("msgget"),exit(-1);    struct mymsg msg1 = {1,"hello1"};    struct mymsg msg2 = {2,"hello2"};    int res1 = msgsnd(msgid,&msg1,            sizeof(msg1)-4,0);    int res2 = msgsnd(msgid,&msg2,            sizeof(msg2)-4,0);    if((res1==0)&&(res2==0))printf("send ok\n");}----------------------------------------------------------msgtypeb.c#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/msg.h>#include <string.h>struct mymsg{    long mtype; //类型    char buf[256];// 数据};int main(){    key_t key = ftok(".",100);    int msgid = msgget(key,0);    if(msgid==-1) perror("msgget"),exit(-1);    struct mymsg msg;    int res = msgrcv(msgid,&msg,sizeof(msg)-4,        -2,0);    if(res==-1) perror("msgrcv"),exit(-1);    printf("mtype=%ld,msg=%s\n",msg.mtype,            msg.buf);}
0 0
原创粉丝点击