ipc msg

消息队列MSG(多进程ipc):
(1)管道与消息队列都是由内核来管理的进程间通讯机制
(2)消息队列类似于管道却又比管道更加人性化,管道的读端只要是管道里有消息都会将其读走,而消息队列是有选择性地去读取数据,只要不是它想要地都不会读走
(3)当消息队列的写端往消息队列写入数据时,读端还没打开,数据会一直在消息队列中等待它读端打开

进程间通讯(ipc)之消息队列:
1.在任意进程间有选择性地进行通讯的方式
2.发送数据时需要携带一定的消息标志
3.消息队列创建后由于是存在于内核中由内核管理,使用过后需要人工删除以释放资源
4.当一个发送方往消息队列中发送数据时,接收方一直还没接收,数据会一直在消息队列里等待接收方的出现

函数原型

//创建键值函数
//函数头文件
#include <sys/types.h>
#include <sys/ipc.h>
//函数原型
key_t ftok(const char *pathname, int proj_id);
//函数介绍:
/******************************************************** 函数作用:用于创建一个键值, 键值作用 :用于进程间通讯(ipc)时的一个标识符 形参:pathname:路径名-->通过哪一个路径来获得键值 proj_id( project identifier):项目id:即我们指定给它一个8位(一个字节,最大256)的整数, 注:其实可以看成路径下的消息队名为给它的数 返回值: 成功:新生成且未被使用的键值 失败:-1 ********************************************************/
//获取消息队列的id号,也可使用参数在不存在的情况下创建
//函数头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
//函数原型
int msgget(key_t key, int msgflg);
//函数介绍:
/******************************************************** 函数作用:用于获取一个消息队列的id号或者创建一个消息队列 形参:key:键值,通过使用ftok函数创建返回的一个键值 msgflg:所对应的操作: IPC_CREAT :键值key所对应的消息队列不存在则创建 (创建时需要给它一个权限使用方法类似于open函数,在后面使用位或或上操作权限) O_EXCL:键值key对应的消息队列存在则报错 注:当键值key被指定为IPC_PRIVATE时,系统自动分配一个键值来对应消息队列 返回值: 成功:返回消息队列的标识符 失败:-1 ********************************************************/

//消息队列用于发送和接收的函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);
/******************************************************** 函数作用: 形参:msqid:通过msgget函数获取到的消息队列id号 msgp:一个自己定义的消息队列结构体的地址 这个结构体一般形式有: struct msgbuf { long mtype; //消息的标识符,且必须大于0 char mtext[1]; //消息正文,数组大小由自己定义 }; 注:结构体第一个元素必须为long类型的标识符!!! msgsz:发送数据的正文的大小,取决于消息队列结构体中mtext数组的大小 msgtyp:消息队列接收函数中用于选择接收的数据的消息标识符 msgflg:参数有 0 :阻塞写入或读取数据 IPC_NOWAIT:往消息队列或写入或读取数据时不阻塞等待 MSG_NOERROR:消息长度超出 msgsz时截断信息且不报错 返回值: msgsnd: 成功: 0 失败:-1 msgrcv: 成功:读取到的字节数 失败:-1 ********************************************************/
//获取或设置删除消息队列函数
//函数头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
//函数原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
/******************************************************** 函数作用:获取消息队列属性,设置消息队列属性或删除消息队列 形参:msqid:通过msgget函数获取到的消息队列id号 cmd:IPC_STAT:获取消息队列的属性,储存到struct msqid_ds *buf中 IPC_SET:把消息队列的属性设置为struct msqid_ds *buf中的属性 IPC_RMID:删除消息队列 IPC_INFO:获取当前系统消息队列的限制值信息 MSG_INFO:获取当前系统消息队列的相关资源消耗情况 buf:一个struct msqid_ds类型的变量的地址,这个结构体的成员有: struct msqid_ds { struct ipc_perm msg_perm; //消息队列的所有权和权限 time_t msg_stime; //消息队列最后一次发送信息的时间 time_t msg_rtime; // 最后一次一次接收信息的时间 time_t msg_ctime; // 最后一次更改消息队列状态时间 unsigned long __msg_cbytes; //当前消息队列的数据大小 msgqnum_t msg_qnum; //当前消息队列的消息个数 msglen_t msg_qbytes; //消息队列最大的数据大小 pid_t msg_lspid; //最后一次发送信息的进程id号 pid_t msg_lrpid; //最后一次接收信息的进程id号 }; 返回值: 成功: IPC_STAT:0 IPC_SET:0 IPC_RMID:0 IPC_INFO:内核中记录所有消息队列信息的数组的下标最大值 MSG_INFO:内核中记录所有消息队列信息的数组的下标最大值 失败:-1 ********************************************************/

测试代码:
发送端

/* 消息队列发送 */
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
//设计消息队列结构体,数组大小为30
struct msgdata
{ 
    long type;
    char data[30];
};
int main()
{ 
    //申请一个消息队列结构体变量
    struct msgdata msg_sed;
    //清空一下结构体变量
    bzero(&msg_sed,sizeof(msg_sed));
    //产生键值,第二个值可以为随机值,只要前面创建其他队列没有使用过
    key_t key = ftok(".",1);
    if(key == -1)
    { 
        //创建失败直接退出
        perror("ftok failed");
        return -1;
    }
    //创建消息队列给0666权限,返回一个msgid
    int msgid = msgget(key,IPC_CREAT | 0666);
    if(msgid == -1)
    { 
        //创建失败直接退出
        perror("msgget failed");
        return -1;
    }
    //不断发送数据
    while(1)
    { 
        //每次发送前清空一下结构体里的内容
        bzero(&msg_sed,sizeof(msg_sed));
        printf("请输入需要发送的数据:");
        //发送类型为1
        msg_sed.type = 1;
        fgets(msg_sed.data,30,stdin);
        //打印一下字符串长度和内容
        //printf("%ld\n",strlen(msg_sed.data) );
        //printf("%s\n",msg_sed.data );
        //往消息队列发送数据
        msgsnd(msgid,&msg_sed,strlen(msg_sed.data),0);
    }
    //删除消息队列
    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

/* 消息队列接收 */

#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
//设计消息队列结构体
struct msgdata
{ 
    long type;
    char data[30];
};
int main()
{ 
    //申请一个消息队列结构体变量
    struct msgdata msg_rcv;
    //
    key_t key = ftok("./",1);
    if(key == -1)
    { 
        perror("ftok failed");
        return -1;
    }
    //获取消息队列id号,如果不存在则创建
    int msgid = msgget(key,IPC_CREAT | 0666);
    if(msgid == -1)
    { 
        perror("msgget failed");
        return -1;
    }
    //接收数据
    while(1)
    { 
        //每次清空一下结构体变量里的内容
        bzero(&msg_rcv,sizeof(msg_rcv));
        //msgrcv(msgid,&msg_rcv,30,1,0);
        //从消息队列读取数据,并判断是否读取成功
        int ret = msgrcv(msgid, &msg_rcv, 30 ,1, 0);
        if(ret == -1)
        { 
            perror("error");
        }
        printf("接收到的数据%s", msg_rcv.data);
    }
    //删除消息队列
    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

测试结果:
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值