进程间通信(2)消息队列

消息队列也是一种用于进程间通信的方式,它放在计算机内核中,并由消息队列表示符(类比文件描述符)标识,它由操作系统维护。

消息队列的特点:

1>它支持进程间双向无阻塞的通信。

2>它是面向消息传递的。

3>它的生命周期是随计算机内核的。

下图列出了消息队列的最大消息的一些数据。

在创建一个消息队列时需要这几个函数:

int msgget(key_t key, int msgflg);

key:由ftok函数创建

msgflg:有ICP_CREAT和ICP_ECXL两个宏参数,第一个参数为新创建一个如果系统中有则返回这个id,第二个参数一般和第一个组合使用为了新创建一个。

key_t ftok(const char *pathname, int proj_id);

该函数第一个参数是指定的路径,第二个参数可由用户自定义一个数,返回一个由这个参数组成的一个数。

每个队列创建好都有一个 msqid_ds与其关联

上面的一个数据结构就是消息队列所维护的结构体,而下面那个结构体则是每一个IPC都要维护的一个结构。


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

msgctl是用于在消息队列结束时做的一些工作,第二个参数cmd会有一些不同的宏参数来让它执行不同的功能。

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

msgsnd用于发送消息,msgp是一个结构体,原型如下:

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

msgbuf中的mtype是用于标识接受的是来自谁的消息或者是谁发送的消息,mtext则适用于存放消息的数组了。

msgflg用于指定消息以什么方式传输---IPC_NOWAIT(消息已满会返回错误,类似于非阻塞传输),如果没有设置或设置为零则以阻塞方式发送,

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

msgtyp>0时返回以msgtyp标识的第一条消息

msgtyp==0时返回消息队列中的第一条消息

msgtyp<小于0时返回绝对值等于msgtyp标识的消息若消息有若干个则返回类型最小的消息


下面是一个简单的阻塞方式的消息队列;

.h

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<sys/types.h>
 4 #include<sys/ipc.h>
 5 #include<sys/msg.h>
 6 #include<string.h>
 7 
 8 #define _PATH_ "."
 9 #define _PROJECT_ID_ 0x6666
 10 #define _MAX_BUF_ 1024  
 11 #define _SERVER_ID_ 1
 12 #define _CLIENT_ID_ 2
 13 
 14 typedef struct msgvp
 15 {
 16     long mtype;
 17     char mmsg_buf[_MAX_BUF_];
 18 }msgvp;
  19 static int comm_msgget(int flag)
  20 {
  21     key_t key=ftok(_PATH_,_PROJECT_ID_);
  22     if(ftok<0)
  23     {
  24         perror("ftok");
  25         exit(1);
  26     }   
  27     int msg_id=msgget(key,flag);
  28     if(msg_id<0)
  29     {
  30         perror("msg_id");
  31         exit(1);
  32     }   
  33     return msg_id;
  34 }   
  35 
  36 int get_msgid()
  37 {
  38     umask(0);
  39     int msg_id=comm_msgget(IPC_CREAT|IPC_EXCL|0666);
  40     return msg_id;
  41 }   
  42 
  43 int use_msgid()
    44 {
    45     int msg_id=comm_msgget(IPC_CREAT);
    46     return msg_id;
    47 }
    48 
    49 void msg_receive(int msg_id,msgvp*msg_vp,int msgvp_size,long mstype)
    50 {
    51     memset(msg_vp->mmsg_buf,‘\0‘,sizeof(msg_vp->mmsg_buf));
    52     if(msgrcv(msg_id,msg_vp,msgvp_size,mstype,0)<0)
    53     {
    54         perror("msgsve");
    55     }
    56 }
    57 
    58 void msg_send(int msg_id,msgvp*msg_vp,int msgvp_size,char *str,int msgtype)
    59 {
    60     memset(msg_vp->mmsg_buf,‘\0‘,sizeof(msg_vp->mmsg_buf));
    61     strcpy(msg_vp->mmsg_buf,str);
    62     msg_vp->mtype=msgtype;
    63     if(msgsnd(msg_id,msg_vp,msgvp_size,0)<0)
    64     {
    65         perror("msgsnd");
    66     }
    67 }
    68 
    69 void msg_distory(int msg_id)
    70 {
    71     if(msgctl(msg_id,IPC_RMID,0)<0)
    72     {
    73             perror("msgctl");
    74     }
    75 }

server.c

  1 #include"comm.h"
  2 
  3 
  4 int main()
  5 {
  6     int msg_id=get_msgid();
  7     msgvp serve;
  8     char my_buf[_MAX_BUF_];
  9     while(1)
 10     {
 11         sleep(5);
 12         msg_receive(msg_id,&serve,sizeof(serve),_CLIENT_ID_);
 13         printf("client:%s",serve.mmsg_buf);
 14 
 15         printf("please write to client:");
 16         fflush(stdout);
 17         int size=read(0,my_buf,_MAX_BUF_);
 18         if(size>0)
 19         {
 20                 my_buf[size]=‘\0‘;
 21         }
 22         msg_send(msg_id,&serve,sizeof(serve),my_buf,_SERVER_ID_);
 23     }
 24 
 25     msg_tory();
 26     return 0;
 27 }
~                                                                                                               
"server.c" 27L, 443C                                                                          1,16         全部

client.c

   

  1 
  2 #include"comm.h"
  3 
  4 
  5 int main()
  6 {
  7     int msg_id=use_msgid();
  8     msgvp client;
  9     char my_buf[_MAX_BUF_];
 10     while(1)
 11     {
 12         printf("please write to server:");
 13         fflush(stdout);
 14         int size=read(0,my_buf,_MAX_BUF_);
 15         if(size>0)
 16         {
 17             my_buf[size]=‘\0‘;
 18         }
 19         msg_send(msg_id,&client,sizeof(client),my_buf,_CLIENT_ID_);
 20 
 21 
 22         sleep(5);
 23         msg_receive(msg_id,&client,sizeof(client),_SERVER_ID_);
 24         printf("server:%s",client.mmsg_buf);
 25 
 26     }
 27     return 0;
 28 }
"client.c" 28L, 441C                                                                          1,0-1        全部

                 

时间: 2024-10-16 00:16:41

进程间通信(2)消息队列的相关文章

进程间通信(6) - 消息队列posix

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.介绍 消息队列是先进先出FIFO原则. 消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权限的进程则可以从消息队列中读走消息.消息队列是随内核持续的. 目前主要有两种类型的消息队列:POSIX消息队列以及System V消息队列,System V消息队列目前被

Linux系统编程——进程间通信:消息队列

消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法,其特点如下: 1)消息队列可以实现消息的随机查询.消息不一定要以先进先出的次序读取,编程时可以按消息的类型读取. 2)消息队列允许一个或多个进程向它写入或者读取消息. 3)与无名管道.命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除. 4)每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的. 5)消息队列是消息的链表,存放在内存中,由内核维护.只有内核重启或人工删除消息队列时,该消息队列才会被删

linux进程间通信之消息队列

我们已经知道进程通信的方式是有多种的,在上一篇博客中讲述了通过管道实现简单的进程间通信,那么接下来我们看看与之类似的另一种方式,通过消息队列来实现进程间通信. 什么是消息队列 消息队列提供了一种由一个进程向另一个进程发送块数据的方法.另外,每一个数据块被看作有一个类型,而接收进程可以独立接收具有不同类型的数据块.消息队列的好处在于我们几乎可以完全避免同步问题,并且可以通过发送消息屏蔽有名管道的问题.更好的是,我们可以使用某些紧急方式发送消息.坏处在于,与管道类似,在每一个数据块上有一个最大尺寸限

练习--LINUX进程间通信之消息队列MSG

https://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 继续坚持,或许不能深刻理解,但至少要保证有印象. ~~~~~~~~~~~~~~ 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix通信机制之一的信号能够传送的信息量有限,后来虽然POSIX 1003.1b在信号的实时性方面作了拓广,使得信号在传递信息量方面有了相当程度的改进,但是信号这种通信方式更像"即时"的通信方式,它要求接受信号的进程在某

[转]Linux进程间通信——使用消息队列

点击此处阅读原文 另收藏ljianhui的专栏初学Linux 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信--使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的

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

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信--使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条消息

Linux进程间通信(消息队列/信号量+共享内存)

写在前面 不得不说,Deadline果真是第一生产力.不过做出来的东西真的是不堪入目,于是又花了一早上重写代码. 实验内容 进程通信的邮箱方式由操作系统提供形如 send()和 receive()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上.在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱

进程间通信之消息队列通信

概念 消息队列 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 消息队列也有管道一样的不足,就是每条消息的最大长度是有上限的(MSGMAX),每个消息队列的总字节数(内核缓冲上限)是有上限的(MSGMNB),系统上消息队列的总数(消息条目数)也有一个上限(MSGMNI) 对比: 管道 消息 流管道 有边界 先进先出 可以后进入.先出来 消息大小三大限制 cat /proc/sys/kernel/msgmax最

进程间通信之消息队列

什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. 相关接口函数 ftok函数 头文件 #include <sys/types.h> #include <sys/ipc.h> 函数原型 key_t ftok( const char * fname, int id

进程间通信(7) - 消息队列System V

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.介绍 System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的系统内核中,后来商用UNIX系统基本都加入了System V IPC的功能. System V消息队列相对于POSIX消息队列的区别主要是: --POSIX消息队列