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 msgs;
  int msg_type;
  char str[256];
  int ret_value;
  int msqid;  

  msqid=msgget(MSGKEY,IPC_EXCL);  /*检查消息队列是否存在*/
  printf("msqid:%d \n",msqid);
  if(msqid < 0){
    msqid = msgget(MSGKEY,IPC_CREAT|0666);/*创建消息队列*/
     printf("msqid:%d \n",msqid);
    if(msqid <0){
    printf("failed to create msq | errno=%d [%s]\n",errno,strerror(errno));
    exit(-1);
    }
  }   

  while (1){
    printf("input message type(end:0):");
    scanf("%d",&msg_type);
    if (msg_type == 0)
       break;
    printf("input message to be sent:");
    scanf ("%s",str);
    msgs.msgtype = msg_type;
    strcpy(msgs.msgtext, str);
    /* 发送消息队列 */
	printf("msqid:%d,msgs.msgtext: %s,size:%d\n",msqid,msgs.msgtext,sizeof(msgs.msgtext));
    ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT);
    printf("sendXxdl(),ret_value:%d,sizeof(struct msgstru):%d \n",ret_value,sizeof(struct msgstru));
    if ( ret_value < 0 ) {
       printf("msgsnd() write msg failed,errno=%d[%s]\n",errno,strerror(errno));
       exit(-1);
    }
  }
  msgctl(msqid,IPC_RMID,0); //删除消息队列
}

/*receive.c */

/*receive.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];
};  

/*子进程,监听消息队列*/
void childproc(){
  struct msgstru msgs;
  int msgid,ret_value;
  char str[512];  

  while(1){
     msgid = msgget(MSGKEY,IPC_EXCL );/*检查消息队列是否存在 */
     if(msgid < 0){
        printf("msq not existed! errno=%d [%s]\n",errno,strerror(errno));
        sleep(2);
        continue;
     }
     /*接收消息队列*/
     ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0);
     printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid());
  }
  return;
}  

void main()
{
  int i,cpid;
  printf("open receive\n");
  /* create 5 child process */
  for (i=0;i<1;i++){
     cpid = fork();
     if (cpid < 0)
        printf("fork failed\n");
     else if (cpid ==0) /*child process*/
        childproc();
  }
}

实现linux进程通信的方式有5种:
--信号(Singal)
--管道(Pipe)
--消息队列(Message)
--信号量(Semaphore)

消息队列
一、概念
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;有读权限的进程则可以读走消息。读走就没有了。消息队列是随内核持续的。 只有内核重启或人工删除时,该消息才会被删除。在系统范围内,消息队列与键值唯一对应。

消息队列的数据结构
1.struct msqid_ds *msgque[MSGMNI]向量:
msgque[MSGMNI]是一个msqid_ds结构的指针数组,每个msqid_ds结构指针代表一个系统消息队列,msgque[MSGMNI]的大小为MSGMNI=128,也就是说系统最多有MSGMNI=128个消息队列
2.struct msqid_ds
一个消息队列结构
struct msqid_ds 中主要数据成员介绍如下:
struct msqid_ds
{
struct ipc_perm msg_perm;
        struct msg *msg_first;                                     /*消息队列头指针*/
        struct msg *msg_last;                                     /*消息队列尾指针*/
        __kernel_time_t msg_stime;                          /*最后一次插入消息队列消息的时间*/
        __kernel_time_t msg_rtime;                          /*最后一次接收消息即删除队列中一个消息的时间*/
        __kernel_time_t msg_ctime; 
        struct wait_queue *wwait;                                /*发送消息等待进程队列*/
        struct wait_queue *rwait;  
        unsigned short msg_cbytes;
        unsigned short msg_qnum;                             /*消息队列中的消息个数*/
        unsigned short msg_qbytes;
        __kernel_ipc_pid_t msg_lspid;                        /*最后一次消息发送进程的pid*/
        __kernel_ipc_pid_t msg_lrpid;                         /*最后一次消息发送进程的pid*/
};
3.struct msg 消息节点结构:
msqid_ds.msg_first,msg_last维护的链表队列中的一个链表节点
struct msg
{
       msg *msg_next;              /*下一个msg*/
       long msg_type;                /*消息类型*/
       *msg_spot;                       /*消息体开始位置指针*/
        msg_ts;                           /*消息体长度*/
        message;                     /*消息体*/
}
4.msgbuf消息内容结构:
msg 消息节点中的消息体,也是消息队列使用进程(消息队列发送接收进程)发送或者接收的消息
struct msgbuf
{
        long mtype;        --消息类型
        char mtext[n];     --消息内容
}

二、步骤及思路
1、取得键值
2、打开、创建消息队列
3、发送消息
4、接收消息
下面具体看看:
1、取得键值
      key_t ftok(char *pathname, char proj)
头文件为<sys/ipc.h>。返回文件名对应的键值,失败返回 -1。proj是项目名,随便写,不为0就行。
fname就是你指定的文件名(已经存在的文件名)。需要有-t 的权限,或用root权限执行,通常设为/tmp或设为" . "。这里我感觉不用这个函数也行,因为key值可以自己指定,例如: #define KEY_MSG 0x101
2、打开、创建消息队列
     int msgget(key_t key, int msgflg)
头文件为<sys/msg.h>。key由ftok获得。
msgflg有:
IPC_CREAT 创建新的消息队列,应配有文件权限0666。
IPC_EXCL  与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
IPC_NOWAIT 读写消息不阻塞。
当没有与key相对应的消息队列并且msgflg中包含了IPC_CREAT标志 或 key的参数为IPC_PRIVATE 时,创建一个新的消息队列。
3、发送消息
         int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
向消息队列发送一条消息。msqid为消息队列的id,msgp为存放消息的结构体。msgsz是消息的长度,和数组的大小不一样哦。msgflg为消息标志,通常为0,也可以为IPC_NOWAIT。出错返回 -1。
消息格式
      struct msgbuf  {
                   long mtype;
                   char mtext[100];
      };
4、接收消息
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg)
从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指定的msgbuf结构中。读取后队列中的消息将会删除。size为结构体中数据的大小,不要计算msgtyp。出错返回 -1。

时间: 2024-10-10 22:56:23

Linux:进程通信之消息队列Message实例的相关文章

Linux程序设计学习笔记----System V进程通信之消息队列

一个或多个进程可向消息队列写入消息,而一个或多个进程可从消息队列中读取消息,这种进程间通讯机制通常使用在客户/服务器模型中,客户向服务器发送请求消息,服务器读取消息并执行相应请求.在许多微内核结构的操作系统中,内核和各组件之间的基本通讯方式就是消息队列.例如,在 MINIX 操作系统中,内核.I/O 任务.服务器进程和用户进程之间就是通过消息队列实现通讯的. Linux中的消息可以被描述成在内核地址空间的一个内部链表,每一个消息队列由一个IPC的标识号唯一的标识.Linux 为系统中所有的消息队

进程通信(消息队列)

消息队列与管道不同的是,消息队列是基于消息的, 而管道是基于字节流的,且消息队列的读取不一定是先入先出.消息队列与命名管道有一 样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节 数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI). IPC对象数据结构 内核为每个IPC对象维护一个数据结构(/usr/include/linux/ipc.h) struct ipc_perm { key_t __key; /* Key supplied t

进程通信之消息队列

消息队列就是一些消息的列表.用户可以在消息队列中添加消息和读取消息等.消息存在于内核中,有“队列ID”来标识 msgget函数语法: msgsnd函数语法: msgrcv函数语法: msgctl函数语法: 添加消息代码: /* msgsnd.c 添加消息*/ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdl

linux进程间的通信(C): 消息队列

一.消息队列(message queue) 消息队列也是System V IPC机制之一. 消息队列与命名管道类似, 但少了打开和关闭管道方面的复杂性. 但使用消息队列并未解决我们在使用命名管道时遇到的一些问题, 如管道满时的阻塞问题. 消息队列提供了一种在两个不相关进程间传递数据的简单有效的方法. 与命名管道相比, 消息队列的优势在于,它独立于发送和接收进程而存在, 这消除了在同步命名管道的打开和关闭时可能产生的一些困难. 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 而且,

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

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

Linux进程通信(二)IPC消息队列

一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度MSGMNI来限制消息队列的总数. 二.IPC对象数据结构 内核为每个IPC对象维护一个数据结构(/usr/include/linux/ip

Linux 进程间通信(posix消息队列 简单)实例

Linux 进程间通信(posix消息队列 简单)实例 详情见: http://www.linuxidc.com/Linux/2011-10/44828.htm 编译: gcc -o consumer consumer.c -lrt gcc -o producer producer.c -lrt /* * * Filename: producer.c * * Description: 生产者进程 * * Version: 1.0 * Created: 09/30/2011 04:52:23 PM

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

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

linux进程通信

e14: 进程间通信(进程之间发送/接收字符串/结构体): 传统的通信方式: 管道(有名管道 fifo,无名管道 pipe) 信号 signal System V(基于IPC的对象):                             IPC对象:                                                    ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ] ... 消息队列 mes