消息队列的进程间通信


消息队列的结构
在这里插入图片描述

读取消息队列中的某个消息,要知道消息队列的msqid和msg_type

ftok函数的使用

key_t ftok( char * fname, int id )
//系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
参数:
fname就时你指定的文件名(该文件必须是存在而且可以访问的)。
id是子序号, 虽然为int,但是只有8个比特被使用(0‐255)。
返回值:
当成功执行的时候,一个key_t值将会被返回,否则 ‐1 被返回
key_t ftok(char * fname, int proj_id);

常见问题:

1.pathname是目录还是文件的具体路径,是否可以随便设置

2.pathname指定的目录或文件的权限是否有要求

3.proj_id是否可以随便设定,有什么限制条件

解答:

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

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

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

一个进程向消息队列发送数据块

代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
struct msgbuf
{
        long mtype;//消息类型
        char mtest[128];
        char ID[4];
};

int main()
{
        struct msgbuf sendbuf;
        int msgid;
        key_t key;
        key=ftok("b.c",5);
        msgid = msgget(key,0755|IPC_CREAT);
        if(msgid == -1)
        {
                printf("create message queue failed!\n");
                  return -1;
        }
        system("ipcs -q");
        printf("create message queue success msgid =%d\n",msgid);

        //init msgbug
        sendbuf.mtype = 100;
        while(1)
        {
        memset(sendbuf.mtest,0,128);//清空数据
        printf("please input to  massage queue:\n");
        fgets(sendbuf.mtest,128,stdin);
        msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.mtest),0);

        }
        return 0;

}

通过ftok函数获得一个消息队列关联值key,然后根据key来创建(存在就打开)一个消息队列,并取得它的msqid给msgid变量里,创一个数据块,且结构体里必须包含long mtype;//消息类型,因为后面从消息队列中读取消息要根据msqid和mtype来找到要读取的消息。

另一个进程读取消息队列的数据块

代码:
msg_write.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
struct msgbuf
{
        long mtype;
        char mtest[128];
        char ID[4];
};

int main()
{
        struct msgbuf readbuf;
        int msgid;
        int readret;
        key_t key;
        key=ftok("b.c",5);
        msgid = msgget(key,0755|IPC_CREAT);
        if(msgid == -1)
        {
                printf("create message queue failed!\n");
                        return -1;
        }
        system("ipcs -q");
        printf("create message queue success msgid =%d\n",msgid);

        //init msgbug
        readbuf.mtype = 99;
        while(1)
        {
        memset(readbuf.mtest,0,128);//清空数据
        readret=msgrcv(msgid,(void *)&readbuf,128,100,0);

        printf("message is: %s\n",readbuf.mtest);
        printf("total have %d byte\n",readret);
        }
        return 0;


根据msgid和my要读取刚刚msg_write.c里把发送给消息队列的消息。
执行结果:
请添加图片描述

一些注意的细节:
key_t ftok( char * fname, int id ),因为key是根据第一个参数:fname文件里的信息和第二个参数id结合产生的,所以fname文件如果删除重新创建,那么它的文件信息就会发送改变,则key值也会发生改变。


版权声明:本文为m0_57678852原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。