进程间通信——消息队列

      前面的两篇博客分别介绍了两种进程间通信的方式:匿名管道、命名管道。下面在介绍一种方式——消息队列。


1.基本概念

      消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为是一个类型,接收者进程接收的数据块可以有不同的类型值。并且消息队列是随内核的,也就是说进程已经退出了,如果不自主释放资源,消息队列是会悄无声息的存在着。所以较管道来说,消息队列的生命周期更加持久,需要手动释放资源。同时,消息队列不一定是先进先出,且每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。

     消息队列就是一个链表。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。    


 2.消息队列的基本结构

 1)IPC对象数据结构内核为每个IPC对象维护一个数据结构


     其中,可以看到许多id信息,uid为拥有者的id;gid为组用户的id;cuid和cgid中的c为创建者;mode为模式,即权限;seq为顺序值。其中key为目标获取(get)时的标志,类似于端口号。

2)消息队列结构


3)消息队列函数

头文件:#include<sys/types.h>

             #include<sys/ipc.h>

             #include<sys/msg.h>

     msgget:int msgget(key_t key, int msgflg);

注:

           key: 可以认为是一个端口号,也可以由函数ftok生成。

           msgflg:

           IPC_CREAT:如果IPC不存在,则创建一个IPC资源,否则打开操作。

           IPC_EXCL:只有在共享内存不存在的时候,新的共享内存建立,存在就产生错误。

          a.  如果单独使用IPC_CREAT,XXXget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标志符。

          b.  如果将IPC_CREAT和IPC_EXCL标志一起使用,XXXget()将返回一个新建的IPC标识符;如果该IPC资源已经存在,就返回-1。     

          c .  IPC_EXCL标志本身并没有太大意义,但是和IPC_CREAT标志一起使用可用来保证所得的对象是新建的,而不是打开已有的对象。System V IPC使用key_t值作为它们的名字,在Redhat linux(后续验证默认都在该平台下)下key_t被定义为int类型

    

     ftok:key_t ftok(const char* pathname, int id);

              函数ftok把一个已经存在的路径名和一个整数识得转换成一个key_t值,称为IPC键。pathname就是你指定的文件名,id是子序列,其中只有8个bit被使用,该函数把从pathname导出的信息与id的低序8为组合成一个整数IPC键。
     msgsnd:int msgsnd(int msqid, const void * msgp, size_t msgsz, int msgflg);

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

其中:

     msqid:消息队列的标识码

     msgp:指向消息队列的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下:

                  struct msgstru{ 

                            long mtype;//大于0

                            char mtext[用户指定大小];

                   }

     msgsz:消息的大小

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

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


    msgctl: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标识的消息队列。


3.客户端和服务器通信

——comm.h文件


——comm.c文件


——client.c文件


——server.c文件


运行结果:


注意:在运行的期间可能会存在以下的问题:



这是因为已经运行过程序,系统会创建消息队列,消息队列必须需要手动进行解除,然后再次进行运行,就可以了。

       ipcs -q ——显示消息队列相关信息

       ipcrm -q——参数为输入显示的key值或者msqid的值










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值