linux 进程间通信(IPC)一消息队列

本文介绍了Linux下进程间通信的消息队列机制,它允许不相关进程间的数据传递,且独立于进程存在,避免了命名管道的同步和阻塞问题。消息队列操作包括msgget、msgrcv、msgsnd和msgctl等函数,每个数据块有长度限制。示例程序msg1.c展示了发送者如何创建并发送消息,以及接收者如何接收并结束时清理消息队列。
摘要由CSDN通过智能技术生成

消息队列提供了一种在两个不相关的进程之间传递数据的相当简单且有效的方法。与命名管道相比,消息队列的优势在于,它独立于发送和接收进程而存在,这消除了在同步命名管道的打开和关闭时可能产生的一些困难。

我们可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题。

但是与管道一样,每个数据块都有一个最大限度的长度限制。


消息队列的函数:

#include <sys/msg.h>


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

int msgget(key_t key,int msgflg);   创建和访问一个消息队列

int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg);从一个消息队列中获取消息

int msgsnd(int msqid,const void *msg_ptr,size_t msg_sz,int msgflg);把消息添加到消息队列中


msg1.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>

#include<sys/msg.h>

struct my_msg_st{
   long int my_msg_type;
   char some_text[BUFSIZ];
};

int main()
{
   int running=1;
   int msgid;
   struct my_msg_st some_data;
   long int msg_to_receive=0;

   //建立消息队列
   msgid=msgget((key_t)1234,0666|IPC_CREAT);
   
   if(msgid==-1)
   {
      fprintf(stderr,"msgget failed with error: %d\n",errno);
      exit(EXIT_FAILURE);
   }
   //从队列中获取消息,直到遇见end为止
   while(running)
   {
      if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1)
      {
        fprintf(stderr,"msgrcv failed with error: %d\n",errno);
        exit(EXIT_FAILURE);
      }
      printf("You wrote: %s",some_data.some_text);
      if(strncmp(some_data.some_text,"end",3)==0)
          running=0;
    }
    if(msgctl(msgid,IPC_RMID,0)==-1)
    {
       fprintf(stderr,"msgctl(IPC_RMID) failed\n");
       exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

msg2.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <sys/msg.h>

#define MAX_TEXT 512

struct my_msg_st{
    long int my_msg_type;
    char some_text[MAX_TEXT];
};

int main()
{
  int running=1;
  struct my_msg_st some_data;
  int msgid;
  char buffer[BUFSIZ];
  
  msgid=msgget((key_t)1234,0666|IPC_CREAT);
  
  if(msgid==-1)
  {
    fprintf(stderr,"msgget failed with error: %d\n",errno);
    exit(EXIT_FAILURE);
  }
  
  while(running)
  {
    printf("Enter some text: ");
    fgets(buffer,BUFSIZ,stdin);
    some_data.my_msg_type=1;
    strcpy(some_data.some_text,buffer);
    
    if(msgsnd(msgid,(void *)&some_data,MAX_TEXT,0)==-1)
    {
      fprintf(stderr,"msgsnd failed\n");
      exit(EXIT_FAILURE);
    }
    if(strncmp(buffer,"end",3)==0)
       running=0;
  }
  exit(EXIT_SUCCESS);
}

与管道不同,这里不再需要由进程自己来提供同步方法,这是消息队列相对于管道的一个明显优点。

发送者程序通过msgget来创建一个消息队列,然后用msgsnd向队列中增加消息。接收者用msgget获得消息队列标识符,然后开始接收消息,直到接收到特殊的文本end为止。然后用msgctl来删除消息队列以完成清理工作。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值