Linux进程间通信——消息队列

1.概述

消息队列是一种通过链表结构组织的一组消息。与其他两种进程间通信(共享内存、信号量)相同,都存放在内核中。多个进程通过消息队列的标识符对消息数据进行传送,实现进程间通信。

2.消息队列的相关操作

使用消息队列实现进程间通信,需要首先用msgget()函数创建一个消息队列,然后调用msgsnd()函数向该消息队列中发送指定的消息,通过msgrcv()函数接收该消息,最后调用msgctl()函数对消息队列进行指定的控制操作,这样一个使用消息队列实现进程间通信就实现了。
2.1 msgget()函数
该函数用于创建一个新的消息队列或打开一个已经存在的消息队列,该函数的定义为:

#include <sys/tyoes.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);

参数说明:
key: 表示所创建的消息队列的名字。
msgflg: 用于设置消息队列的访问权限,也可以表示该函数的操作类型。
如果该函数调用成功,返回值为与参数key相关联的标识符;如果调用失败,则返回-1.
注意:创建消息队列的函数msgget()中参数所遵循的原则与创建共享内存的shmget()函数类似。
2.2 msgsnd()函数
msgsnd()函数用于向消息队列中发送消息,该函数定义如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg);

msqid: 将信息发送到消息队列的标识符。
msgp: 指向要发送的消息数据。
msgsz: 以字节数表示的消息数据的长度。
msgflg: 消息队列满时的处理方法,该参数可以是0或IPC_NOWAIT.
该函数调用成功返回0;失败返回-1.
要发送的数据存放在msgbuf结构体中,使用msgp指针指向该类型引用消息数据的内容和消息的类型。msgbuf结构体定义如下:

struct msgbuf
{
	long mtype; /*消息类型,以大于0的整数表示*/
	char mtext[1]; /*消息内容*/
};

如果消息队列中有足够的空间,msgsnd()函数会立即返回,并实现发送消息到msgp指定的消息队列中; 如果消息队列已满的话,msgflg参数没有设置IPC_NOWAIT值,则msgsnd()将会阻塞;如果设置了IPC_NOWAIT值,则msgsnd()函数调用失败,并返回-1,直到消息队列中有空间时,函数才返回0.
2.3 msgrcv()函数
msgrcv()函数用于接收消息队列中的消息数据,该函数定义如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void* msgp, size_t msgsz, long msgtyp, int msgflg);

msqid: 从msqid标识符所代表得消息队列中接收消息。
msgp: 指向存放消息数据的内存空间。
msgsz: 以字节数表示的消息数据的长度。
msgtyp: 读取的消息数据的类型。
msgflg: 对读取的消息数据不满足情况的处理。
该函数调用成功时,返回0;如果调用失败,返回-1.
2.4 msgctl()函数
该函数主要实现对消息队列的控制操作,该函数定义如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct maqid_ds* buf);

msgctl()函数实现对msqid标识符所指向的消息队列进行控制,控制内容取决于参数cmd的取值。

命令 说明
IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值
IPC_SET 在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值
IPC_RMID 删除消息队列

3.消息队列实现进程间通信

在Linux系统中,使用msgget()函数创建一个消息队列,通过msgsnd()函数发送两次消息,第一次发送消息内容为:“hello Linux!”,第二次发送的消息为"Goodbye!"。接下来调用msgrcv()函数接收消息,这样就实现了一个消息队列的进程间通信。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    key_t key;
    int proj_id = 1;
    int msqid;
    char message1[] = {"Hello Linux!"};
    char message2[] = {"Goodbye!"};
    struct msgbuf
    {
	long msgtype; //消息类型
	char msgtext[1024]; //消息内容
    }snd, rcv;
    key = ftok("/root/process/mq", proj_id);
    if(key == -1)
    {
	perror("create key error!");
	return 1;
    }
    if((msqid = msgget(key, IPC_CREAT|0666)) == -1)
    {
	printf("msgget error!\n");
	exit(1);
    }
    snd.msgtype = 1;
    sprintf(snd.msgtext, message1);
    if(msgsnd(msqid, (struct msgbuf*) &snd, sizeof(message1)+1, 0) == -1)
    {
	printf("msgsnd error!\n");
	exit(1);
    }
    snd.msgtype = 2;
    sprintf(snd.msgtext,"%s", message2);
    if(msgsnd(msqid,(struct msgbuf*)&snd, sizeof(message2)+1, 0) == -1)
    {
    printf("msgrcv error!\n");
    exit(1);
    }
    if(msgrcv(msqid,(struct msgbuf*)& rcv, 80, 1, IPC_NOWAIT) == -1)
    {
	printf("msgrcv error!\n");
	exit(1);
    }
    printf("the received message: %s\n", rcv.msgtext);
    msgctl(msqid, IPC_RMID, 0); /*删除新创建的消息队列*/
    exit(0);
}

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章