进程通信(消息队列)

消息队列与管道不同的是,消息队列是基于消息的,
而管道是基于字节流的,且消息队列的读取不一定是先入先出。消息队列与命名管道有一
样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节
数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。

IPC对象数据结构
内核为每个IPC对象维护一个数据结构(/usr/include/linux/ipc.h)
struct ipc_perm {
key_t __key; /* Key supplied to xxxget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};

1.创建新消息队列或取得已存在消息队列
原型:int msgget(key_t key, int msgflg);
参数:
key:可以认为是一个端口号,也可以由函数ftok生成。
msgflg:
IPC_CREAT 如果IPC不存在,则创建一个IPC资源,否则打开操作。
IPC_EXCL:只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。
如果单独使用IPC_CREAT,XXXget()函数要么返回一个已经存在的共享内存的操作符,要
么返回一个新建的共享内存的标识符。
如果将IPC_CREAT和IPC_EXCL标志一起使用,XXXget()将返回一个新建的IPC标识符
;如果该IPC资源已存在,或者返回-1。
IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证
所得的对象是新建的,而不是打开已有的对象。

2.向队列读/写消息
原型:
msgrcv从队列中取用消息:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int
msgflg);
msgsnd将数据放到消息队列中:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msqid:消息队列的标识码
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可
定义的通用结构,形态如下:
struct msgstru{
long mtype; //大于0
char mtext[用户指定大小];
};
msgsz:消息的大小。

msgtyp:从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都
会被读取。

msgflg:用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常
数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已满,则msgsnd()将不会阻塞,而
会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时,不做等待马上返回-1,并设定
错误码为ENOMSG。当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取
阻塞等待的处理模式。

3.设置消息队列属性
原型:int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
参数:msgctl 系统调用对 msgqid 标识的消息队列执行 cmd 操作,系统定义了 3 种 cmd 操作
: IPC_STAT , IPC_SET , IPC_RMID
IPC_STAT : 该命令用来获取消息队列对应的 msqid_ds 数据结构,并将其保存到 buf 指
定的地址空间。
IPC_SET : 该命令用来设置消息队列的属性,要设置的属性存储在buf中。
IPC_RMID : 从内核中删除 msqid 标识的消息队列。

key_t键
System V IPC使用key_t值作为它们的名字,在Redhat linux(后续验证默认都在该平台下)下
key_t被定义为int类型
ftok函数
函数ftok把一个已存在的路径名和一个整数标识得转换成一个key_t值,称为IPC键:
# include <sys/types.h>
# include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
该函数把从pathname导出的信息与id的低序8位组合成一个整数IPC键。

comm.h
  1 #pragma once
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<sys/ipc.h>
  6 #include<sys/types.h>
  7 #include<sys/msg.h>
  8 #define _PATH_ ".tmp"
  9 #define SIZE 100
 10 #define _PROJ_ID 0x444
 11 #define _client_ 2
 12 #define _server_ 1
 13 
 14 typedef struct _msginfo
 15 {
 16   long mtype;
 17   char mtext[SIZE];
 18 }msginfo;
 19 int create_msg_set();
 20 int get_msg_set();
 21 int rec_msg_set(int,char*,long);
 22 int send_msg_set(int,char*,long);
 23 int destroy_msg_set(int);
 
 
 comm.c
  1 #include "comm.h"
  2 static int com_creat_msg_set(int flags)
  3 {
  4   key_t key=ftok(_PATH_,_PROJ_ID);
  5   if(key<0)
  6   {
  7    perror("ftok");
  8   return -1;
  9   }
 10   int _msg_id=msgget(key,flags);
 11   if(_msg_id<0)
 12   {
 13    perror("msgget");
 14    return -1;
 15   }
 16 return _msg_id;
 17 }
 18 int creat_msg_set()
 19 {
 20   int flags=IPC_CREAT|IPC_EXCL|0666;
 21   return com_creat_msg_set(flags);
 22 }
 23 int get_msg_set()
 24 {
 25 
 26   int flags=IPC_CREAT;
 27   return com_creat_msg_set(flags);
 28 }
 29 
 30 int rec_msg_set(int _msg_id,char* msg,long mtype)
 31 {
 32 
 33   msginfo _info;
 34   memset(_info.mtext,‘\0‘,sizeof(_info.mtext));
 35  if(msgrcv(_msg_id,&_info,SIZE-1,mtype,0)<0)
 36 {
 37   perror("msgrcv");
 38   return -1;
 39 }
 40 strcpy(msg,_info.mtext);
 41 return 0;
 42 }
 43 
 44 
 45 int send_msg_set(int _msg_id,char *msg,long mtype)
 46 {
 47 
 48   msginfo _info;
 49   memset(_info.mtext,‘\0‘,sizeof(_info.mtext));
 50   strcpy(_info.mtext,msg);
 51 //  gets(_info.mtext);
 52  _info.mtype=mtype;
 53  if(msgsnd(_msg_id,&_info,strlen(_info.mtext),0)<0)
 54 {
 55   perror("msgsnd");
 56   return -1;
 57 }
 58  return 0;
 59 
 60 }
 61 
 62 
 63 int destroy_msg_set(int _msg_id)
 64 {
 65   if(msgctl(_msg_id,IPC_RMID,NULL)<0)
 66   {
 67    perror("msgctl");
 68    return -1;
 69   }
 70   return 0;
 71 }
                                                                                          
                                                                                          client.c
                                                                                           1 
  2 #include "comm.h"
  3 int main()
  4 {
  5   int _msg_id=creat_msg_set();
  6   char msg[SIZE];
  7   while(1)
  8   {
  9     fflush(stdout);
 10     printf("client:");
 11     memset(msg,‘\0‘,SIZE);
 12     scanf("%s",msg);
 13     send_msg_set(_msg_id,msg,_client_);
 14     //sleep(5);
 15     memset(msg,‘\0‘,SIZE);
 16     printf("server:\n");
 17     rec_msg_set(_msg_id,msg,_server_);
 18     printf("%s",msg);
 19 
 20   }
 21   destroy(_msg_id);
 22   return 0;
 23 }

  server.c
  1 #include "comm.h"
  2 int main()
  3 {
  4   int _msg_id=get_msg_set();
  5   char msg[SIZE];
  6   while(1)
  7   {
  8     //sleep(5);
  9     printf("client:");
 10     rec_msg_set(_msg_id,msg,_client_);
 11     printf("%s",msg);
 12     fflush(stdout);
 13     memset(msg,‘\0‘,sizeof(msg));
 14     //sleep(5);
 15     printf("server:\n");
 16     scanf("%s",msg);
 17     send_msg_set(_msg_id,msg,_server_);
 18 
 19   }
 20   return 0;
 21 }
      
      
 Makefile:
                                                                                           1 .PHONY:all
  2 all:client server
  3 client: client.c comm.c
  4     gcc -o [email protected] $^
  5 server:server.c comm.c
  6     gcc -o [email protected] $^
  7 .PHONY:clean
  8 clean:
  9     rm -f client server 
   
  
  结果:
[[email protected] message]$ ./client
client:naihao
server:
woclient:
nihao
server:
aiclient: 

 [[email protected] message]$ ./server
client:naihaoserver:
wo ai ni
client:nihaoserver:
niaho
时间: 2024-08-09 10:45:24

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

【Linux】 进程通信--消息队列

一.概念 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我们可以通过发送消息 来避免命名管道的同步和阻塞问题.消息队列与管道不同的是,消息队列是基于消息的, 而管道是基于字节流的,且消息队列的读取不?定是先入先出.消息队列与命名管道有一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有?个上限(MSGMNI). 查看机

linux内核---进程通信---消息队列

转自:https://blog.csdn.net/ljianhui/article/details/10287879 原文地址:https://www.cnblogs.com/qing1991/p/10182521.html

在Windows系统上实现轻量级的线程间及进程间消息队列

看IaaS 资料时,捎带研究下硬件虚拟化,主要参考<基于intel VT-x 的Xen 全虚拟化实现>,<intel 开发手册 第三卷 19/20章> Intel VT 是intel X86架构的CPU硬件虚拟化技术,新增两种模式: VM root: 即虚拟机管理系统运行模式: VM non root:即虚拟机运行模式: 如下图: VMXON.VMXOFF用以实现打开或关闭虚拟化功能: VM Exit和VM Entry 用以实现non root和root之间的切换:这种转换被VMC

linux 进程间消息队列通讯

转自:http://blog.csdn.net/lifan5/article/details/7588529 http://www.cnblogs.com/kunhu/p/3608589.html 前言: 消息队列是内核地址空间中的内部链表,通过linux内核在各个进程之间传递内容,消息顺序地发送到消息队列中,并且以几种不同的方式 从队列中获取,每个消息队列可以用IPC标识符唯一的进行标识,内核中的消息队列是通过IPC的标识符来区别的,不同的消息队列之间是 相互独立的,每个消息队列中的消息又构成

[PHP] 多进程通信-消息队列使用

向消息队列发送数据和获取数据的测试 <?php $key=ftok(__FILE__,'a'); //获取消息队列 $queue=msg_get_queue($key,0666); //发送消息 //msg_send($queue, 1, "Hello, 1"); //接收消息,如果接收不到会阻塞 msg_receive($queue, 1, $message_type, 1024, $message1); //移除消息 //msg_remove_queue($queue); /

μC/OS-II 任务的同步与通信 --- 消息队列

简介 使用消息队列可以在任务之间传递多条消息.消息队列由三个部分组成:事件控制块.消息队列和消息. 当把事件控制块成员 OSEventType 的值置为 OS_EVENT_TYPE_Q 时,该事件控制块描述的就是一个消息队列. 消息队列相当于一个共用一个任务等待列表的消息邮箱数组,事件控制块成员 OSEventPtr 指向了一个叫做队列控制块(OS_Q)的结构,该结构管理了一个数组 MsgTbl[ ],该数组中的元素都是一些指向消息的指针. 消息队列的数据结构 其中,可以移动的指针为 OSQIn

【进程编程】——msg进程间的消息队列通信

           [进程编程]--msg进程间的消息队列通信 消息队列就像一个链表,先进先出,就像排队打饭,先到先买!键值 用来获取消息队列的描述字,我感觉就像是一个定位标识符! 函数一     key_t ftok(char *pathname,char proj)返回的是一个键值------>创建队列之前一定要获取这个键值!proj:项目名,不为零即可 打开.创建函数二     int msgget(key_t key,int msgflg) //看见没,这里是要求键值的. key:键值

Linux:进程通信之消息队列Message实例

/*send.c*/ /*send.c*/ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define MSGKEY 1024 struct msgstru { long msgtype; char msgtext[2048]; }; main() { struct msgstru ms

[转]Linux进程通信之POSIX消息队列

进程间的消息队列可以用这个实现,学习了下. http://blog.csdn.net/anonymalias/article/details/9799645?utm_source=tuicool&utm_medium=referral 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点: 一个进程向消息队列写入消息之前,并不需要某个进程在该队列上等待该消息的到达,而管道和FIFO是相

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

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