进程通信之IPC通信对象——信息队列

IPC通信------IPC对象:1,共享内存,2,消息队列3,信号灯。
2,消息队列(链式队列)



msgget()创建函数的解析:

msgctl()释放函数的解析:

例子1:利用msgget()函数创建消息队列,再用msgctl()删除消息队列;创建creat_delete_massegeque.c,代码如下:

#include"unistd.h"
#include"sys/types.h"
#include"sys/msg.h"
#include"signal.h"
#include"stdio.h"
#include"stdlib.h"

int main()
{
    int msgid;
    //创建或打开消息队列
    msgid=msgget(IPC_PRIVATE,0777);
    if(msgid<0)
    {
        printf("creat message queue failure\n");
        return -1;
    }
    printf("create message queue success\n");
    system("ipcs -q");//查看消息队列属性
    
     //删除消息队列
    msgctl(msgid,IPC_RMID,NULL);
    system("ipcs -q");
    return 0;
 }
    

编译源文件,并运行./mque,结果如图:


可见,消息队列成功被创建后,又成功被删除了。

msgsnd()写入函数的解析:

例子2:基于例子1,在创建的消息队列里写入数据:
创建msgsnd.c文件,内容如下:

#include"unistd.h"
#include"sys/types.h"
#include"sys/msg.h"
#include"signal.h"
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
//消息节点
typedef struct MsgNode{
        long type;
        char voltage[124];
        char ID[4];
 }MsgNode;
 
int main()
{
    int msgid;
    MsgNode snd;
    //创建或打开消息队列
    msgid=msgget(IPC_PRIVATE,0777);
    if(msgid<0)
    {
        printf("creat message queue failure\n");
        return -1;
    }
    printf("create message queue success\n");
    system("ipcs -q");//查看消息队列属性
    
      //向消息队列写入数据
      fgets(snd.voltage,124,stdin);//从标准输入写入
      msgsnd(msgid,(void*)&snd.voltage,strlen(snd.voltage),0);
      system("ipcs -q");
      while(1);
     //删除消息队列
    msgctl(msgid,IPC_RMID,NULL);
    system("ipcs -q");
    return 0;
 }

我们写入 :helloeveryone welcome to daily dictation共41个字符。运行结果如下图:

msgrcv读函数解析:

例子3:基于例子2,读出消息队列里的数据:
创建msgrcv.c文件,内容如下:

#include"unistd.h"
#include"sys/types.h"
#include"sys/msg.h"
#include"signal.h"
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
//消息节点
typedef struct MsgNode{
        long type;
        char voltage[124];
        char ID[4];
 }MsgNode;
 
int main()
{
    int msgid;
    int readret;//读返回的字符个数
    MsgNode snd;//写对象
    MsgNode red;//读对象
    //创建或打开消息队列
    msgid=msgget(IPC_PRIVATE,0777);
    if(msgid<0)
    {
        printf("creat message queue failure\n");
        return -1;
    }
    printf("create message queue success\n");
    system("ipcs -q");//查看消息队列属性
    
        //init snd
        snd.type=100;
      //向消息队列写入数据
      printf("please input message:\n");
      fgets(snd.voltage,124,stdin);//从标准输入写入
      msgsnd(msgid,(void*)&snd,strlen(snd.voltage),0);
      //system("ipcs -q");
      
      //clear voltage buf before read
      memset(red.voltage,0,124);
      //从消息队列里读数据
      readret=msgrcv(msgid,(void*)&red,124,100,0);
      printf("the result read from message queue\n");
      printf("red.voltage=%sreadret=%d\n",red.voltage,readret);
      
     //删除消息队列
    msgctl(msgid,IPC_RMID,NULL);
    system("ipcs -q");
    return 0;
 }

写入之后hello linux!, 读出结果如下:

读出hello linux!。
【注意】对消息队列的读相当于对链表的删除,写相当于对消息队列的插入,所以读完队列里的消息就不在了。

综合实例:采用消息队列实现两个非亲缘关系进程A和B之间的双向通信;(多进程收发:主进程发,子进程收)。
【用来体现消息队列与管道通信和共享内存通信的区别和优点】
server的主进程写,子进程读;client的主进程读,子进程写。

建立server.c,client.c, a.c文件,如图:

server.c实现代码如下:

#include"unistd.h"
#include"sys/types.h"
#include"sys/msg.h"
#include"signal.h"
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
//message node
typedef struct MsgNode{
        long type;
        char voltage[124];
        char ID[4];
 }MsgNode;
 
int main()
{
        int msgid;
        int readret;//return number of string
        MsgNode sndbuf;//write object
        MsgNode redbuf;//read object
        int key;
        
        key=ftok("./a.c",'a');//creat key for message queue
        if(key<0)
        {
        printf("creat key failure\n");
        return -1;
        }
        printf("creat key success, key=%d\n",key);

        //creat or open message queue
        msgid=msgget(key,IPC_CREAT | 0777);
        if(msgid<0)
        {
        printf("creat message queue failure\n");
        return -2;
        }
        printf("create message queue success\n");
        system("ipcs -q");//check attributes of massege  queues
        
        pid_t pid;
        pid=fork();//fork child process pid
        if(pid>0)
        {
        //init sndbuf type
        sndbuf.type =100;
        while(1)
        {
        //clear sndbuf before write
        memset(sndbuf.voltage,0,124);
        //send message to client
        printf("please send message to client:\n");
        fgets(sndbuf.voltage,124,stdin);//write message from stdin to sndbuf
        msgsnd(msgid,(void*)&sndbuf,strlen(sndbuf.voltage),0);//write message to msgque 
        }
        }

        //child process code    
        if(pid==0)
        {
        while(1)
        {
        //clear redbuf before read
        memset(redbuf.voltage,0,124);
        //read message from messageque
        readret=msgrcv(msgid,(void*)&redbuf,124,200,0);
        printf("\ncontent of message queue:\n");
        printf("type = %ld\n",redbuf.type);
        printf("red.voltage=%sreadret=%d\n",redbuf.voltage,readret);
        }
        }

        //delete or free message queue
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
    return 0;
 }

client.c实现代码如下:

#include"unistd.h"
#include"sys/types.h"
#include"sys/msg.h"
#include"signal.h"
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
//message node
typedef struct MsgNode{
        long type;
        char voltage[124];
        char ID[4];
 }MsgNode;
 
int main()
{
        int msgid;
        int readret;//return number of message
        MsgNode sndbuf;//writed object
        MsgNode redbuf;//read object
        int key;
        
        key=ftok("./a.c",'a');//creat key
        if(key<0)
        {
        printf("creat key failure\n");
        return -1;
        }
        printf("creat key success, key=%d\n",key);
                
        //creat or open message queue
        msgid=msgget(key,IPC_CREAT | 0777);
        if(msgid<0)
        {
        printf("creat message queue failure\n");
        return -2;
        }
        printf("create message queue success\n");
        system("ipcs -q");//check message attributes
        
        pid_t pid;
        pid=fork();//creat child process pid
        
        //parent process code
        if(pid>0)
        {
        while(1)
        {
        //clear redbuf before read message
        memset(redbuf.voltage,0,124); 
        //read message from msgque
        readret=msgrcv(msgid,(void*)&redbuf,124,100,0);
        printf("message queue are:\n");
        printf("red.voltage=%sreadret=%d\n",redbuf.voltage,readret);
        }
        }

        if(pid==0)
        {
        //init type
        sndbuf.type=200;
        while(1)
        {
        //clear sndbuf before write 
        memset(sndbuf.voltage,0,124);
        printf("please send message to server\n");
        fgets(sndbuf.voltage,124,stdin);//write message from stdin
        msgsnd(msgid,(void*)&sndbuf,strlen(sndbuf.voltage),0);//write to message queue
        }
        }

        //delete message queue
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
    return 0;
 }

以上是消息队列通信的总结。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值