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

从以下4个函数来说消息队列:msgget、msgrcv、msgsnd、msgctl

1、msgget函数:创建消息队列

原型:int msgget(key_t key,int msgflg)

参数:

 key:为键值,可设置成常数IPC_PRIVATE,或由ftok获取;例(key_t)1234

 msgflg是标志位,设定的权限,

      标志位如下:

      IPC_CREAT,创建新的队列;

      IPC_EXCL,与IPC_CREAT一起使用,表示如果要创建的消息队列已经存在,则返回错误;

      IPC_NOWAIT,读写消息队列要求无法达到满足时,立即返回,不会出现堵塞

 返回值:成功返回消息队列描述符 msgid,失败返回-1

 

2、msgsnd函数:写数据到消息队列中  

原型:int msgsnd(int msqid,struct msgbuf *msgp,size_t msgz,int msgflg)

  msqid为消息队列ID,由内核反馈

  msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构

struct msgbuf
{
    long type;    /* 消息类型,必须 > 0 */
    char mtext[1]; /* 消息文本 */ 
};

msgsz:消息的大小。

返回值:成功返回0;失败返回-1,并将失败原因保存在errno中。

 

3、msgrcv函数:读出消息队列的数据

 原型:int msgrcv(int msqid,struct msgbuf *msgp,int msgz,long msgtype,int msgflg)

 从msqid代表的消息队列中读取一个msgtype类型的消息,并把消息存储在msgp指定的msgbuf结构中,在成功地读取了一条消息后将删除。

msgtype:消息类型
         msgtyp等于0 则返回队列的最早的一个消息。
         msgtyp大于0,则返回其类型为mtype的第一个消息。
         msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进 程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时 候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就 会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。

 返回值:成功,返回实际读取的字节数;失败,返回-1。

4、msgctl函数:控制消息队列

原型:int msgctl(int msqid,int cmd,struct msqid_ds *buf)

msgctl系统调用对msqid标识的消息队列执行cmd操作

cmd:

     IPC_STAT,读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中。
     IPC_SET,设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
     IPC_RMID,从系统内核中移走消息队列。

返回值:成功返回0;失败返回-1。

以下是两个队列之间通信的代码:

msg1.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
 
#include <sys/types.h>
#include <sys/ipc.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(-1 == msgid)
    {
        fprintf(stderr,"msgget failed with error:%d\n",errno);
        exit(EXIT_FAILURE);
    }
 
    /*循环从消息队列中接收消息*/
    while(running)
    {
        /*读取消息*/
        if(-1 == msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0))
        {
            fprintf(stderr,"msgrcv failed with error:%d\n",errno);
            exit(EXIT_FAILURE);
        }
 
        printf("You wrote:%s",some_data.some_text);
 
        /*接收到消息为“end”时结束循环*/
        if(0 == strncmp(some_data.some_text,"end",3))
        {
            running = 0;
        }
    }
 
        /*从系统内核中移走消息队列*/
        if(-1 == msgctl(msgid,IPC_RMID,0))
        {
            fprintf(stderr,"msgctl(IPC_RMID) failed!\n");
            exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
}


msg2.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
 
#include <sys/types.h>
#include <sys/ipc.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(-1 == msgid)
    {
        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(-1 == msgsnd(msgid,(void *)&some_data,MAX_TEXT,0))
        {
            fprintf(stderr,"msgsnd failed!\n");
            exit(EXIT_FAILURE);
        }
 
        /*用户输入的为“end”时结束循环*/
        if(0 == strncmp(buffer,"end",3))
        {
            running = 0;
        }
    }
    exit(EXIT_SUCCESS);
}

调试结果:

./msg1

You wrote:2
You wrote:dss
You wrote:end

./msg2

Enter some text:2
Enter some text:dss
Enter some text:end

参考博客:https://blog.csdn.net/echo_ana/article/details/52904384

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值