Linux进程间通信(IPC)之消息队列简单编程

1.消息队列的概述

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

2.消息队列的特点

  • 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
  • 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
  • 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
  •  消息队列可以互相通信,而管道和FIFO是不可以互相通信的(因为管道和FIFO是半双工)。
3.消息队列常用API
int msgget(key_t key, int flag);// 创建或打开消息队列:成功返回队列ID,失败返回-1
int msgsnd(int msqid, const void *ptr, size_t size, int flag);// 添加消息:成功返回0,失败返回-1
int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);// 读取消息:成功返回消息数据的长度,失败返回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buf);// 控制消息队列:成功返回0,失败返回-1

4.消息队列的节点是一个链表

struct msgbuf
{
    long mtype;             //消息的类型
    char mtext[128];        //消息的大小
};

5.键值的生成

key是一个索引,需要去内核去找消息队列的ID。
ftok():是系统IPC键值的格式转换函数。系统建立IPC通信(消息队列、信号量和共享内存)时必须指定一个ID值,通常情况下,该id值通过ftok函数得到。
key_t ftok(const char *fname,int id)
fname:就是你指定的文件名(已经存在的文件名),一般使用当前目录。
id:是子序号
在UNIX时实现中,是将文件的索引节点号取出,前面在加上子序号得到key_t 的返回值
如:
key_t key;
key=ftok(".",'z');

6. 创建消息队列

int msgget(key_t key, int flag);

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

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

          ②key 参数为 IPC_PRIVATE。

msgget(key,IPC_CREAT|0777);

 7.消息队列的数据发送

int msgsnd(int msqid, const void *ptr, size_t size, int flag);

第一个参数:消息队列的ID

第二个参数:数据存放的内存地址

第三个参数:发送的大小

第四个参数:一般为0

msgsnd(msgID,&writebuf,strlen(writebuf.mtext),0);

8.消息队列的数据接收

int msgrcv(int msqid, void *ptr, size_t size, long type,int flag)

第一个参数:消息队列的ID

第二个参数:数据存放的地址

第三个参数:存放的大小

第四个参数:消息的类型

第五个参数:一般为0,为阻塞状态,直到读到数据。

msgrcv(msgID,&readbuf,sizeof(readbuf.mtext),888,0);

9.消息队列的移除

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

第一个参数:消息队列的ID

第二个参数:IPC_RMID 移除指令

第三个参数:一般为NULL

msgctl(msgID,IPC_RMID,NULL);

10.消息队列的简单通信代码

msgread.h

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



int main()
{
        key_t key;
        key=ftok(".",'z');
        printf("key=%x\n",key);
        struct msgbuf readbuf;
        struct msgbuf writebuf={888,"hello world!"};
        int msgID=msgget(key,IPC_CREAT|0777);
        if(msgID==-1){
                printf("create msg failed\n");
        }
        msgsnd(msgID,&writebuf,strlen(writebuf.mtext),0);
        msgrcv(msgID,&readbuf,sizeof(readbuf.mtext),988,0);
        printf("read=%s\n",readbuf.mtext);
        msgctl(msgID,IPC_RMID,NULL);
        return 0;
}

msgread.c

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



int main()
{
        key_t key;
        key=ftok(".",'z');
        printf("key=%x\n",key);
        struct msgbuf readbuf;
        struct msgbuf writebuf={988,"hello world!222"};
        int msgID=msgget(key,IPC_CREAT|0777);
        if(msgID==-1){
                printf("create msg failed\n");
        }
        msgrcv(msgID,&readbuf,sizeof(readbuf.mtext),888,0);
        printf("read=%s\n",readbuf.mtext);

        msgsnd(msgID,&writebuf,strlen(writebuf.mtext),0);
        msgctl(msgID,IPC_RMID,NULL);
        return 0;
}
~  

你可能感兴趣的:(linux)