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

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点:

        1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。

        2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。

        3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的            类型读取。

原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// 创建或打开消息队列:成功返回队列ID,失败返回-1
1 int msgget(key_t key, int flag);
 // 添加消息:成功返回0,失败返回-1
2 int msgsnd(int msqid, const void *ptr, size_t size, int flag);
// 读取消息:成功返回消息数据的长度,失败返回-1
3 int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
 // 控制消息队列:成功返回0,失败返回-1
4 int msgctl(int msqid, int cmd, struct msqid_ds *buf);//一般来说第三个参数设置为NULL

在以下两种情况下,msgget将创建一个新的消息队列:

  • 如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。
  • key参数为IPC_PRIVATE

函数msgrcv在读取消息队列时,type参数有下面几种情况:

  • type == 0,返回队列中的第一个消息;
  • type > 0,返回队列中消息类型为 type 的第一个消息;
  • type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。

可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。(其他的参数解释,请自行度娘)

ftok系统IPC键值的格式转换函数

系统建立IPC通讯 (消息队列信号量共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

#include <sys/types.h>
#include <sys/ipc.h>
//函数原型:
key_t ftok( const char * fname, int id )
/*fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为当前目录。
id是子序号。虽然是int类型,但是只使用8bits(1-255)。
在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。
查询文件索引节点号的方法是: ls -i
*/

代码示例:

msgGet.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>

struct msgbuf {
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};

int main()
{
        int msgid;
        key_t key;
        struct msgbuf readBuf;
        struct msgbuf writeBuf = {988,"I am get ,thank you for send message"};

        if((key = ftok(".", 'z')) < 0)//获取key值
        {
                perror("ftok");
                exit(0);
        }
        printf("Message Queue get key:%d\n",key);//打印key值
        if((msgid =msgget(key,IPC_CREAT|0777)) == -1)//创建消息队列
        {
                perror("masget error");
                exit(0);
        }
        printf("My msgid is:%d\n",msgid);//打印消息队列ID

        msgrcv(msgid, &readBuf, sizeof(readBuf.mtext),888,0);
        printf("MsgGet: receive msg.mtext is: %s\n", readBuf.mtext);
        printf("MsgGet: receive msg.mtype is: %ld\n", readBuf.mtype);
        putchar('\n');


        msgsnd(msgid,&writeBuf,sizeof(writeBuf.mtext),0);
        printf("send over\n");

        msgctl(msgid,IPC_RMID,NULL);//移除消息队列

        return 0;
}

msgSend.c

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>

struct msgbuf {
        long mtype;       /* message type, must be > 0 */
        char mtext[128];    /* message data */
};

int main()
{
        int msgid;
        key_t key;
        struct msgbuf writeBuf = {888,"this is message from send"};
        //888 msgGet接受的消息类型
        struct msgbuf readBuf;
        if((key = ftok(".", 'z')) < 0)
        {
                perror("ftok");
                exit(0);
        }
        printf("Message Queue send key:%d\n",key);
        if((msgid =msgget(key,IPC_CREAT|0777)) == -1)
        {
                perror("masget error");
                exit(0);
        }
        printf("My msgid is:%d\n",msgid);

        msgsnd(msgid,&writeBuf,sizeof(writeBuf.mtext),0);
        printf("send over\n");
        putchar('\n');

        msgrcv(msgid, &readBuf, sizeof(readBuf.mtext),988,0);
        //988 msgSend接收的消息类型
        printf("MsgSend: receive msg.mtext is: %s\n", readBuf.mtext);
        printf("MsgSend: receive msg.mtype is: %ld\n", readBuf.mtype);

        msgctl(msgid,IPC_RMID,NULL);//移除消息队列
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

牵猫散步的鱼儿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值