`

IPC SystemV Message Queue

 
阅读更多

SystemV消息队列

<!--[if !supportLists]-->1、 <!--[endif]-->函数列表

<!--[if !supportLists]-->Ø <!--[endif]-->key_t ftok(const char *pathname, int proj_id);

//# include <sys/types.h>

//# include <sys/ipc.h>

IPC消息队列有一个key的属性(类型为key_t),一般由此函数产生,产生方法为:根据文件名pathname(必须存在且有权限访问)得到索引节点号,然后将索引节点号和子序列号(proj_id)组成ID标示。

<!--[if !supportLists]-->Ø <!--[endif]-->int msgget(key_t key, int msgflg);

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

此函数有两个作用:创建key属性为key的消息队列和返回key指定消息的msgid,其中msgid是消息队列的标示。

其中msgflg标示符可以指定创建消息队列的访问权限(一般为S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH用户读写,组和其它读);同时可以指定msgget函数执行的操作,在创建消息队列时,msgflg必须有IPC_CREAT

如果msgflg0,则只返回消息队列的msgid

此函数成功时,返回非负消息队列标示;失败时返回-1

<!--[if !supportLists]-->Ø <!--[endif]-->int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

#include <sys/msg.h>

其中msgidmsgget返回的消息队列标识符,msgp是一个结构体指针,msgsz是结构体中具体数据的长度,msgflg可以为0或者IPC_NOWAIT

msgflag指定IPC_NOWAIT时,msgsnd函数成为非阻塞,当由于一些限制条件(例如没有存放消息的可用空间时)出现时,该函数立即放回。

发送成功返回0,发送失败返回-1.

<!--[if !supportLists]-->Ø <!--[endif]-->ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgsz是结构体(msgp)中保存数据的最大值,也是函数能够返回的最大数据量。而具体的接收的数据量,由函数返回值确定。msgflag可以为0或者IPC_NOWAITmsgtyp指定待接收消息的类型。

msgflag指定为IPC_NOWAIT时,msgrcv函数成为非阻塞,当由于一些限制条件(例如消息队列中没有消息)时,该函数立即返回。

其中type的规则为:

type=0时,返回消息队列中的第一个消息;

type>0时,返回类型值为type的消息;

type<0时,返回类型值小于或者等于type绝对值的消息中类型值最小的消息。

msgrcv函数成功时返回接收消息的数据量,失败返回-1.

<!--[if !supportLists]-->Ø <!--[endif]-->int msgctl(int msqid, int cmd, struct msqid_ds *buf);

消息队列控制函数。Msgid为消息队列标示,cmd为具体的命令(一共有三种),buf用来设置或取得消息队列的msgid_ds结构体。

IPC_RMID:删除msgid指定的消息队列。Buf参数忽略,为0

IPC_SET:设置消息队列msgid_ds结构体的四个成员:msg_perm.uidmsg_perm_gidmsg_perm.modemsg_qbytes。它们的值来自由buf指向的结构体中的相应成员。

IPC_STAT:给调用者返回消息队列msgid_ds结构体,通过buf返回。

<!--[if !supportLists]-->2、 <!--[endif]-->实例解析

<!--[if !supportLists]-->Ø <!--[endif]-->create|send|receive|remove

消息队列的创建和删除、消息的发送和接收。采用默认的struct msgbuf作为消息体。

// mymsgcreate.c

#include <sys/msg.h>

#include <fcntl.h> // O_CREATE

#include <sys/types.h> // pid_t

#include <sys/stat.h>

int main(int argc, char **argv)

{

int c, oflag, mqid;

oflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH | IPC_CREAT;

//设置权限(用户读写,组和其它读)

//指定msgget具体操作(创建消息队列并返回ID

if((mqid = msgget(ftok("test3", 0), oflag))<0)

printf("create error!/n");

//ftokpathname参数所指向的文件必须存在

printf("mqid===%d/n",mqid);

exit(0);

}

//#gcc mymsgcreate.c –o mycreate

创建一个消息队列必须满足的条件是:ftok函数的pathname指向的文件已经存在;msgflg中有IPC_CREATE标示。权限要设置正确,用户要有读和写权限。

// mymsgsnd.c

#include <sys/msg.h>

#include <fcntl.h> // O_CREATE

#include <sys/types.h> // pid_t

#include <sys/stat.h>

int

main(int argc, char **argv)

{

struct msgbuf *ptr;

int mqid;

if((mqid = msgget(ftok("test3", 0), S_IWUSR))<0)

printf("create error!/n");

// S_IWUSR权限可以省略,消息队列的权限已经设置了,这里可以为0

//msgget函数的作用是返回消息队列的ID

ptr = calloc(sizeof(long)+7, sizeof(char));

ptr->mtype = 100;

strcpy(ptr->mtext,"abcdefg");

msgsnd(mqid, ptr,7, 0);

exit(0);

}

// gcc -D_GNU_SOURCE mymsgsnd.c -o mysend

消息队列已经创建了,此时msgget函数只是起获得消息队列标示的作用,因此msgflg可以为0

关于编译选项-D_GNU_SOURCE说明如下:

/usr/include/src/msg.h文件中

#ifdef __USE_GNU
/* Template for struct to be used as argument for `msgsnd' and `msgrcv'. */
struct msgbuf
{
long int mtype; /* type of received/sent message */
char mtext[1]; /* text of the message */
};
#endif

#ifdef _GNU_SOURCE
# define __USE_GNU 1
#endif

因此要想使用struct msgbuf,必须#define _GNU_SOURCE,也可以通过编译选项加进去。

注意msgbuf成员mtext是大小为1的字符数组,而经测试:消息数据的长度不受此限制。例如上面的例子即发送了7个字符。这可能是与结构体成员内存存储有关,也就是可能已经超出结构体的存储范围,这对普通的数据类型是不允许,但对结构体变量是可以的,正如 strcpy(ptr->mtext,"abcdefg");操作是合法的。

//mymsgrec.c

#include <sys/msg.h>

#include <fcntl.h> // O_CREATE

#include <sys/types.h> // pid_t

#include <sys/stat.h>

#define MAXMSG (8192 + sizeof(long))

int

main(int argc, char **argv)

{

int mqid,n;

struct msgbuf *buff;

if((mqid = msgget(ftok("test3", 0), S_IRUSR))<0)

printf("create error!/n");

//S_IWUSR权限可以省略,消息队列的权限已经设置了,这里可以为0

//msgget函数的作用是返回消息队列的ID

buff = malloc(MAXMSG);

n =msgrcv(mqid, buff, MAXMSG, 100, 0);

printf("read %d bytes, type = %ld,mtext=%s/n", n, buff->mtype,buff->mtext);

exit(0);

}

// gcc -D_GNU_SOURCE mymsgrec.c -o myrec

通消息发送,此时消息队列已经创建,msgget函数只起获得消息队列标示的作用,msgflg可以为0.

//mymsgrmid.c

#include <sys/msg.h>

#include <fcntl.h> // O_CREATE

#include <sys/types.h> // pid_t

#include <sys/stat.h>

int

main(int argc, char **argv)

{

int mqid;

mqid = msgget(ftok("test3", 0), 0);

msgctl(mqid, IPC_RMID, 0);

exit(0);

}

//gcc mymsgrmid.c –o myrm

struct msqid_ds *buf参数被忽略,为0

<!--[if !supportLists]-->Ø <!--[endif]-->mystruct

自定义消息结构体进行消息的发送和接收。

msgsndmsgrcv函数的void* msgp是具有struct msgbuf模板的结构体变量。

首先分析下struct msgbuf的结构。

struct msgbuf
{
long int mtype; /* type of received/sent message */
char mtext[1]; /* text of the message */
};
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

有两个成员,一个为long int保存着消息类型,一个为char数组,保存着具体的消息数据。

因此,以此结构体作为模板的结构体至少有两个成员,一个为long int,一个为char数组。如果结构体的成员变量不只这两个,必须保证保存消息类型的long int和保存消息数据的char数组,连续存储,并位于结构体末尾。

现在自定义一个以struct msgbuf为模板的结构体。

struct mymesg {

long mesg_len; /* #bytes in mesg_data, can be 0 */

long mesg_type; /* message type, must be > 0 */

char mesg_data[MAXMESGDATA];

};

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

两个函数中msgp结构体指针为部分mymesg结构体指针,指向mseg_type。也就是消息接收和发送函数的void* msgp参数为&(ptr->mesg_type)。也就是消息传输的结构体不包含mesg_len成员数据,在接收端,mesg_len通过msgrcv函数的返回值确定。

从实现方式和结果来看,使用struct msgbuf和自定义结构体没有差异。

//mymesg.h

#include <sys/msg.h>

#include <fcntl.h> // O_CREATE

#include <sys/types.h> // pid_t

#include <sys/stat.h>

#include <limits.h>

#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))

#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

struct mymesg {

long mesg_len; /* #bytes in mesg_data, can be 0 */

long mesg_type; /* message type, must be > 0 */

char mesg_data[MAXMESGDATA];

};

//mystructsnd.c

#include "mymesg.h"

int main(int argc, char **argv)

{

struct mymesg *ptr;

int mqid;

if((mqid = msgget(ftok("test3", 0), S_IWUSR))<0)

printf("create error!/n");

ptr = calloc(2*sizeof(long)+7, sizeof(char));

ptr->mesg_type = 100;

ptr->mesg_len = 7;

strcpy(ptr->mesg_data,"abcdefg");

msgsnd(mqid, &(ptr->mesg_type),ptr->mesg_len, 0);

exit(0);

}

// gcc -D_GNU_SOURCE mystructsnd.c -o mystructsend

// mystructrec.c

#include "mymesg.h"

#define MAXMSG (8192 + sizeof(long))

int

main(int argc, char **argv)

{

int mqid,n;

struct mymesg *buff;

if((mqid = msgget(ftok("test3", 0), S_IRUSR))<0)

printf("create error!/n");

buff = malloc(MAXMSG);

buff->mesg_type=100;

n =msgrcv(mqid,&(buff->mesg_type), MAXMSG,buff->mesg_type, 0);

buff->mesg_len=n;

printf("read %d bytes, type = %ld,mtext=%s/n", buff->mesg_len, buff->mesg_type,buff->mesg_data);

exit(0);

}

// gcc -D_GNU_SOURCE mystructrec.c -o mystructrec

<!--[if !supportLists]-->3、 <!--[endif]-->小结

<!--[if !supportLists]-->Ø <!--[endif]-->消息队列和管道(pipeFIFO)的区别:

管道可以比作为“传输带”,货物(数据流)是按照放上去的顺序达到的;

消息队列可以比作为“仓库”,货物是静态地存储的。

管道对于存货和取货的双方有一定的要求:没有存货方,就不能有取货方(管道只能先以写方式打开后,才能以读方式打开);没有货,就不能取货(对管道写数据后,才能读数据);并且对货物形式有要求(存货和取货双方必须定义一致的数据协议)。

消息队列的取货和存货方不存在彼此阻塞约束的现象,双方都是独立自由的,消息队列只是一个公共的存货的仓库;双方也不需要关心数据协议,消息队列已经将数据以消息形式保存在队列中。

<!--[if !supportLists]-->Ø <!--[endif]-->Posix消息队列和SystemV消息队列区别

新的应用程序应考虑使用Posix消息队列,不过大量的现有代码使用SystemV消息队列。

Posix消息队列遗漏的主要特性是从队列中读取指定优先级消息的能力;这两种消息都不适用真正的描述字,因此从而造成在消息队列上使用selectpoll的困难。

<!--[if !supportLists]-->Ø <!--[endif]-->ipcs命令

此命令用于显示系统中进程间通信的内核对象。

#ipcs –qa

显示所有的进程间通信对象

#ipcs –q

显示消息队列对象

<!--[if !supportLists]-->Ø <!--[endif]-->消息复用是指在一个消息队列上存储多个种类的消息,这些消息通过struct msgbufmtype来区分。

<!--[if !supportLists]-->Ø <!--[endif]-->消息队列存在一定的限制,包括:每个消息的最大字节数;任何一个消息队列上的最大字节数;系统范围的最大消息队列数;系统范围的最大消息数。

分享到:
评论

相关推荐

    msgq:System V消息队列(IPC)Python扩展

    ftok:将路径名和项目标识符转换为System V IPC密钥 msgget:获取消息队列标识符 msgsnd:将消息发送到队列 msgrcv:从队列接收消息 msgctl:消息控制操作 有关系统调用的更多信息,请访问您的手册页。 这个想法是...

    用消息队列实现Client和Server间的通信.rar_message queue_server client_消息队列 _消

    7. **消息队列在Unix环境下的应用**:在Unix环境中,消息队列通常是基于POSIX标准的,如System V IPC或Berkeley套接字。这些系统提供了一套API来创建、发送和接收消息,开发者可以利用这些API在C、C++等语言中实现...

    System V共享内存与信号量综合应用之生产者与消费者问题解决

    System V IPC(Interprocess Communication)是Unix/Linux系统中实现进程间通信的一种方式,它提供了三种主要机制:信号量(Semaphore)、消息队列(Message Queue)和共享内存(Shared Memory)。在这个问题中,...

    深入理解linux内核ipc机制

    - **System V IPC** 包括:System V消息队列、System V信号灯、System V共享内存区。 - **Posix IPC** 包括:Posix消息队列、Posix信号灯、Posix共享内存区。 #### 三、IPC机制详解 ##### 1. 管道(Pipe)及有名...

    linux 进程间通讯IPC 讲解PPT 对IPC做出详细讲解,是学习必备ppt www.zmemb.com 交大志盟

    2. 消息队列(Message Queue) 消息队列是一种简单但有效的进程间通信方式,允许进程发送和接收特定格式的消息。它提供了有序的消息传递,并且可以选择性地接收消息。使用`msgget`、`msgsnd`、`msgrcv`和`msgctl`...

    system 5 和posix

    ### System V IPC与POSIX IPC通信机制详解 #### 一、概述 在计算机科学领域,进程间通信(Inter-Process Communication, IPC)是操作系统提供的核心功能之一,它允许不同的进程之间进行数据交换和同步操作。System...

    Linux系统中的进程间通讯机制.pdf

    在 System V IPC 机制中,包括消息队列(message queue)、信号量(semaphore)和共享内存(shared memory)等机制。 System V IPC 机制的实现是通过系统调用来访问 ipc 对象的。进程如果要访问 ipc 对象,需要通过...

    UNIX Network Programming Volume 2(Unix网络编程卷2英文版)

    system v ipc 3.1 introduction 27 3.2 key_t keys and ftok function 28 3.3 ipc_perm structure 30 3.4 creating and opening ipc channels 30 3.5 ipc permissions 32 3.6 identifier reuse 34 3.7 ipcs ...

    操作系统 SYSV进程间通信PPT教案学习.pptx

    在SYSV(System V)操作系统中,提供了多种IPC方式,其中包括信号量(Semaphore)、消息队列(Message Queue)和共享内存(Shared Memory)。本教程将主要讨论SYSV IPC中的信号量。 信号量是一种特殊的同步机制,它...

    试验4进程同步-生产者消费者试验.pdf

    进程间通信机制包括共享内存(shared memory)、信号量(semaphores)和消息队列(Message Queue)等一系列进程通信方式。System V IPC 的进程间通信机制一个显著特点是:在内核中它的具体实例是以对象的形式出现的...

    Android IPC介绍

    Linux系统中,进程间通信的方式主要包括:socket、named pipe、message queue、signal、shared memory等。而在Java系统中,主要依赖socket和named pipe等方式进行进程间的通信。然而,对于Android操作系统而言,其...

    PHP下操作Linux消息队列完成进程间通信的方法

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/   PHP的sysvmsg模块是对Linux系统支持的System V IPC中的System V消息队列函数族的封装。我们需要利用sysvmsg模块提供的函数来进进程间通信。先来看一段...

    进程间通信2,msgq4.c msg_send.c msgl.c msgq1.c

    标题中的“进程间通信2,msgq4.c msg_send.c msgl.c msgq1.c”表明这个主题聚焦在操作系统中的进程间通信(IPC, Inter-Process Communication)技术,特别是使用消息队列(Message Queue)这一机制。消息队列是进程...

    进程间通信.pdf

    2. **System V IPC**:引入了更为复杂且功能强大的机制,如消息队列、信号量和共享内存。 3. **POSIX IPC**:为了标准化IPC接口,POSIX定义了一系列标准,包括线程、消息队列和信号量等。 4. **基于Socket的IPC**:...

    liunx中的消息队列学笔记。

    在Linux系统中,消息队列的实现基于System V IPC(Inter-Process Communication)机制。消息队列可以看作是一个存储在内核空间的队列,由多个消息构成,每个消息有一个类型和数据内容。进程可以通过发送或接收消息来...

    深刻理解Linux进程间通信.pdf

    消息队列(Message Queue)是另一种IPC机制,它允许不同进程间以消息的形式发送和接收数据。消息队列与管道相比,可以实现双向通信,并且消息可以是任意长度的数据。消息队列有自己的限制,例如大小限制以及创建队列...

    UNIX程序设计教学大纲

    5. **进程间通信(IPC)**:掌握管道(pipe)、信号量(semaphore)、共享内存(shared memory)和消息队列(message queue)等IPC机制。 6. **Socket网络编程**:学习TCP/IP协议,编写网络客户端和服务器程序,实现...

Global site tag (gtag.js) - Google Analytics