嵌入式Linux进程间通信——消息队列

一、消息队列概述

        消息队列是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO具有更大的优势。这些消息存在于内核中,由“队列ID”标识。

二、消息队列的应用

(1)函数说明

         消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列:

(1) msgget()创建或打开消息队列:创建的消息队列的数量会受到系统消息队列数量的限制
(2) msgsnd()添加消息:它把消息添加到已打开的信息队列末尾
(3) msgrcv()读取消息:它把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息
(4) msgclt()控制消息队列:它可以完成多项功能

(2)函数格式

msgget()函数语法要点
所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

函数原型 int msgget(key_t key,int msgflg)
函数传入值 key:消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列。
msgflg:权限标志位
函数返回值 成功:消息队列ID
出错:-1
msgsnd()函数语法要点
所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

函数原型 int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
函数传入值 msgid:消息队列的队列ID

msgp:指向消息结构的指针。该消息结构msgbuf通常为:

struct msgbuf

{

     long mtype;          /* 消息类型,该结构必须从这个域开始 */

     char mtext[1];      /* 消息正文 */

}

msgsz:消息正文的字节数(不包括消息类型指针变量)
msgflg: IPC_NOWAIT若消息无法立即发送(比如:当消息队列已满),函数会立即返回
0:msgsnd调阻塞直到发送成功为止
函数返回值 成功:0
出错:-1
msgrcv()函数语法要点
所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

函数原型 int msgrcv(int msgid,void *msgp,size_t msgsz,long int msgtyp,int msgflg)
函数传入值 msqid:消息队列的队列ID
msgp:消息缓冲区,同于msgsnd()函数的msgp
msgsz:消息正文的字节数(不包括消息类型指针变量)
msgtyp: 0:接收消息队列中第一个消息
大于0:接收消息队列中第一个类型为msgtyp的消息
小于0:接收消息队列中第一个类型值不小于msgtyp绝对值且类型值又最小的消息
msgflg: MSG_NOERROR:若返回的消息比msgsz字节多,则消息就会截短到msgsz字节,且不通知消息发送进程
IPC_NOWAIT:若在消息队列中并没有相应类型的消息可接收,则函数立即返回
0:msgrcv()调用阻塞直到接收到一条相应类型的消息为止
函数返回值 成功:0
失败:-1
msgctl()函数语法要点
所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

函数原型 int msgctl(int msgid,int cmd,struct msgid_ds *buf)
函数传入值 msgid:消息队列的队列ID

cmd:

参数命令

IPC_STAT:读取消息队列的数据结构msgid_ds,并将其存储在buf指定的地址中

IPC_SET:设置消息队列的数据结构msgid_ds中的ipc_perm域(IPC操作权限描述结构)值。这个值取自buf参数。

IPC_RMID:从系统中删除消息队列
buf:描述消息队列的msgid_ds结构类型变量
函数返回值 成功:0
出错:-1

(3)使用实例

msgsnd.c

/* msgsnd.c */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define BUFSIZE 512

struct msgbuf
{
   long mtype;
   char mtext[BUFSIZE];
};

int main()
{
   int msgid;
   struct msgbuf msg;

   if((msgid = msgget((key_t)1234,IPC_CREAT|0666)) == -1)
   {
        printf("SEND:msgget error.\n");
        exit(1);
   }

   while(1)
   {
        if(fgets(msg.mtext,BUFSIZE,stdin) == NULL)
        {
            printf("SEND:fgets error.\n");
            exit(1);
        }

        msg.mtype = getpid();
        if(msgsnd(msgid,&msg,BUFSIZE,0) == -1)
        {
            printf("SEND:msgsnd error.\n");
            exit(1);
        }

        if(strncmp(msg.mtext,"quit",4) == 0)
        {
            break;
        }
   }
   exit(0);
}

msgrcv.c

/* msgrcv.c */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFSIZE 512

struct msgbuf
{
    long mtype;
    char mtext[BUFSIZE];
};

int main()
{
    int msgid;
    struct msgbuf msg;

    if(msgid = msgget((key_t)1234,IPC_CREAT|0666) == -1)
    {
        printf("RECV:msgget error.\n");
        exit(1);
    }

    do
    {
        memset(msg.mtext,0,BUFSIZE);
        if(msgrcv(msgid,(void *)&msg,BUFSIZE,0,0) == -1)
        {
            printf("RECV:msgrcv error.\n");
            exit(1);
        }
        printf("RECV:%s\n",msg.mtext);
    }while(strncmp(msg.mtext,"quit",4));

    if(msgctl(msgid,IPC_RMID,NULL) == -1)
    {
        printf("RECV:msgctl(IPC_RMID) error.\n");
        exit(1);
    }

    exit(0);
}

猜你喜欢

转载自blog.csdn.net/q1449516487/article/details/81491139