精华内容
下载资源
问答
  • 进程间通信消息队列 ( message queue ) 消息队列消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....
  • linux c 进程间通信 消息队列 代码 亲测可用
  • 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是...
    一、什么是消息队列
    消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
     
    Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。
     
    二、在Linux中使用消息队列
    Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。它的用法与其他两个System V PIC机制,即信号量和共享内存相似。
     
    1、msgget函数
    该函数用来创建和访问一个消息队列。它的原型为:
     
    1. int msgget(key_t, key, int msgflg);  
    与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。
     
    它返回一个以key命名的消息队列的标识符(非零整数),失败时返回-1.
     
    2、msgsnd函数
    该函数用来把消息添加到消息队列中。它的原型为:
     
    1. int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);  
    msgid是由msgget函数返回的消息队列标识符。
     
    msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,指针msg_ptr所指向的消息结构一定要是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型。所以消息结构要定义成这样:
     
     
    1. struct my_message{  
    2.     long int message_type;  
    3.     /* The data you wish to transfer*/  
    4. };  
    msg_sz是msg_ptr指向的消息的长度,注意是消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度。
     
    msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。
     
    如果调用成功,消息数据的一分副本将被放到消息队列中,并返回0,失败时返回-1.
     
    3、msgrcv函数
    该函数用来从一个消息队列获取消息,它的原型为
     
    1. int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);  
    msgid, msg_ptr, msg_st的作用也函数msgsnd函数的一样。
     
    msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。
     
    msgflg用于控制当队列中没有相应类型的消息可以接收时将发生的事情。
     
    调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.
     
    4、msgctl函数
    该函数用来控制消息队列,它与共享内存的shmctl函数相似,它的原型为:
     
    1. int msgctl(int msgid, int command, struct msgid_ds *buf);  
    command是将要采取的动作,它可以取3个值,
        IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
        IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
        IPC_RMID:删除消息队列
     
    buf是指向msgid_ds结构的指针,它指向消息队列模式和访问权限的结构。msgid_ds结构至少包括以下成员:
     
    1. struct msgid_ds  
    2. {  
    3.     uid_t shm_perm.uid;  
    4.     uid_t shm_perm.gid;  
    5.     mode_t shm_perm.mode;  
    6. };  
    成功时返回0,失败时返回-1.

    转载于:https://www.cnblogs.com/dk666/p/7412332.html

    展开全文
  • linux进程间通信消息队列信号量共享内存等.pptx
  • linux进程间通信消息队列、信号量、共享内存等.ppt
  • 进程创建消息队列和两个子进程p1和p2 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列写入一条消息“ok”,目的是通知进程p2可以读取文件内容了。 子进程p2从消息...
  • 主要介绍了Linux消息队列实现进程间通信实例详解的相关资料,需要的朋友可以参考下
  • 本文实例讲述了Python进程间通信Queue消息队列用法。分享给大家供大家参考,具体如下: 进程间通信-Queue Process之间有时需要通信,操作系统提供了很多机制来实现进程间的通信。 1. Queue的使用 可以使用...
  • 最近在Hi3515上调试Qt与DVR程序,发现他们之间使用消息队列通信的,闲暇之余,就总结了一下消息队列,呵呵,自认为通俗易懂,同时,在应用中也发现了消息队列的强大之处。  关于线程的管理(互斥量和条件变量)见:...
  • 【Linux】进程间通信消息队列

    万次阅读 多人点赞 2018-03-22 23:32:28
    在上一篇博客里,我们学习了进程间通信的一种方式,那就是管道,今天我们继续学习另一种方式消息队列消息队列 一. 什么是消息队列?  消息队列消息的链表,存放在内核中并由消息队列标识符表示。  ...

    在上一篇博客里,我们学习了进程间通信的一种方式,那就是管道,今天我们继续学习另一种方式消息队列

    消息队列

    一. 什么是消息队列?

      消息队列是消息的链表,存放在内核中并由消息队列标识符表示。
      消息队列提供了一个从一个进程向另一个进程发送数据块的方法,每个数据块都可以被认为是有一个类型,接受者接受的数据块可以有不同的类型。
      但是同管道类似,它有一个不足就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数(MSGMNB),系统上消息队列的总数上限(MSGMNI)。可以用cat /proc/sys/kernel/msgmax查看具体的数据。
      内核为每个IPC对象维护了一个数据结构struct ipc_perm,用于标识消息队列,让进程知道当前操作的是哪个消息队列。每一个msqid_ds表示一个消息队列,并通过msqid_ds.msg_first、msg_last维护一个先进先出的msg链表队列,当发送一个消息到该消息队列时,把发送的消息构造成一个msg的结构对象,并添加到msqid_ds.msg_first、msg_last维护的链表队列。在内核中的表示如下:
    这里写图片描述


    二. 特点:

    • 生命周期随内核,消息队列会一直存在,需要我们显示的调用接口删除或使用命令删除
    • 消息队列可以双向通信
    • 克服了管道只能承载无格式字节流的缺点

    三. 消息队列函数

    1.msgget

    功能:创建和访问一个消息队列
    原型

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    int msgget(key_t key, int msgflag);

    参数
    key:某个消息队列的名字,用ftok()产生
    msgflag:有两个选项IPC_CREAT和IPC_EXCL,单独使用IPC_CREAT,如果消息队列不存在则创建之,如果存在则打开返回;单独使用IPC_EXCL是没有意义的;两个同时使用,如果消息队列不存在则创建之,如果存在则出错返回。
    返回值:成功返回一个非负整数,即消息队列的标识码,失败返回-1

    #include <sys/types.h>
    #include <sys/ipc.h>
    key_t ftok(const char *pathname, int proj_id);

    调用成功返回一个key值,用于创建消息队列,如果失败,返回-1

    2.msgctl

    功能:消息队列的控制函数
    原型

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);

    参数
    msqid:由msgget函数返回的消息队列标识码
    cmd:有三个可选的值,在此我们使用IPC_RMID

    • IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值
    • IPC_SET 在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值
    • IPC_RMID 删除消息队列

    返回值
    成功返回0,失败返回-1

    3.msgsnd

    功能:把一条消息添加到消息队列中
    原型

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

    参数
    msgid:由msgget函数返回的消息队列标识码
    msgp:指针指向准备发送的消息
    msgze:msgp指向的消息的长度(不包括消息类型的long int长整型)
    msgflg:默认为0
    返回值:成功返回0,失败返回-1

    消息结构一方面必须小于系统规定的上限,另一方面必须以一个long int长整型开始,接受者以此来确定消息的类型

    struct msgbuf
    {
         long mtye;
         char mtext[1];
    };

    4.msgrcv

    功能:是从一个消息队列接受消息
    原型
    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
    参数:与msgsnd相同
    返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1


    此外,我们还需要学习两个重要的命令
    前面我们说过,消息队列需要手动删除IPC资源
    ipcs:显示IPC资源
    ipcrm:手动删除IPC资源
    这里写图片描述


    下面用代码模拟实现client与server之间的通信
    comm.h

    #ifndef _COMM_H_
    #define _COMM_H_
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <sys/msg.h>
    
    struct msgbuf
    {
        long mtype;
        char mtext[1024];
    };
    
    #define SERVER_TYPE 1
    #define CLIENT_TYPE 2
    
    int createMsgQueue();
    int getMsgQueue();
    int destoryMsgQueue(int msg_id);
    int sendMsgQueue(int msg_id, int who, char* msg);
    int recvMsgQueue(int msg_id, int recvType, char out[]);
    
    #endif
    

    comm.c

    #include "comm.h"
    
    static int commMsgQueue(int flags)
    {
        key_t key = ftok("/tmp", 0x6666);
        if(key < 0)
        {
            perror("ftok");
            return -1;
        }
    
        int msg_id = msgget(key, flags);
        if(msg_id < 0)
        {
            perror("msgget");
        }
        return msg_id;
    }
    
    int createMsgQueue()
    {
        return commMsgQueue(IPC_CREAT|IPC_EXCL|0666);
    }
    
    int getMsgQueue()
    {
        return commMsgQueue(IPC_CREAT);
    }
    
    int destoryMsgQueue(int msg_id)
    {
        if(msgctl(msg_id, IPC_RMID, NULL) < 0)
        {
            perror("msgctl");
            return -1;
        }
        return 0;
    }
    
    int sendMsgQueue(int msg_id, int who, char* msg)
    {
        struct msgbuf buf;
        buf.mtype = who;
        strcpy(buf.mtext, msg);
    
        if(msgsnd(msg_id, (void*)&buf, sizeof(buf.mtext), 0) < 0)
        {
            perror("msgsnd");
            return -1;
        }
        return 0;
    }
    
    int recvMsgQueue(int msg_id, int recvType, char out[])
    {
        struct msgbuf buf;
        int size=sizeof(buf.mtext);
        if(msgrcv(msg_id, (void*)&buf, size, recvType, 0) < 0)
        {
            perror("msgrcv");
            return -1;
        }
    
        strncpy(out, buf.mtext, size);
        out[size] = 0;
        return 0;
    }
    

    server.c

    #include "comm.h"
    
    int main()
    {
        int msgid = createMsgQueue();
    
        char buf[1024] = {0};
        while(1)
        {
            recvMsgQueue(msgid, CLIENT_TYPE, buf);
            if(strcasecmp("quit", buf) == 0)
                break;
            printf("client# %s\n", buf);
    
            printf("Please enter# ");
            fflush(stdout);
            ssize_t s = read(0, buf, sizeof(buf));
            if(s>0)
            {
                buf[s-1]=0;
                sendMsgQueue(msgid, SERVER_TYPE, buf);
                printf("send done, wait recv...\n");
            }
        }
    
        destoryMsgQueue(msgid);
        return 0;
    }
    

    client.c

    #include "comm.h"
    
    int main()
    {
        int msgid = getMsgQueue();
    
        char buf[1024] = {0};
        while(1)
        {
            printf("Please Enter# ");
            fflush(stdout);
            ssize_t s = read(0, buf, sizeof(buf));
            if(s > 0)
            {
                buf[s-1]=0;
                sendMsgQueue(msgid, CLIENT_TYPE, buf);
                if(strcasecmp("quit", buf) == 0)
                    break;
                printf("send done, wait recv...\n");
            }
    
            recvMsgQueue(msgid, SERVER_TYPE, buf);
            printf("server# %s\n", buf);
        }
        return 0;
    }
    

    这里写图片描述
    这里写图片描述

    展开全文
  • 例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据  文件1 创建进程1 终端输入通过消息队列发送数据 #include <stdio.h> #include &...

    例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据

      文件1 创建进程1 终端输入通过消息队列发送数据

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <string.h>
    
    struct msgbuf //消息结构体
    {
        long types;
        char msg[20];
    };
    struct msgbuf mymsgbuf; //定义消息结构变量
    
    int main(int argc, const char *argv[])
    {
        key_t key;
        int msgid;
    
        mymsgbuf.types = 100; //给消息结构赋值
    
        key = ftok("./app",'a');  //建立key值
        if(key < 0)
        {
            perror("ftok fail ");
            exit(1);
        }
    
        // 创建消息队列,如果消息队列存在,errno 会提示 eexist
        // 错误,此时只需要直接打开消息队列即可
        msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
        if(msgid < 0)
        {
            if(errno == EEXIST) //文件存在错误提示
            {
                msgid = msgget(key,0666);//打开消息队列
            }
            else //其他错误退出
            {
                perror("msgget fail ");
                exit(1);
            }
        }
        while(1) //循环从终端获取数据,然后通过消息队列发送出去,输入 “quit” 结束循环
        {
            fgets(mymsgbuf.msg, 10, stdin); //终端获取消息写入消息队列中
            //发送消息
            msgsnd(msgid, &mymsgbuf, sizeof(mymsgbuf)-sizeof(long),0);
            if(strstr(mymsgbuf.msg, "quit")!=NULL)
            {
                break;
            }
        }
        
        //删除消息队列
        msgctl(msgid, IPC_RMID, NULL);
    
        return 0;
    }

    文件 2 创建进程2 ,接收消息队列的数据,打印到终端上

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <string.h>
    
    struct msgbuf //消息结构体
    {
        long types;
        char b[20];
    };
    struct msgbuf mymsgbuf, recvbuf; //定义消息结构变量
    
    int main(int argc, const char *argv[])
    {
        key_t key;
        int msgid;
    
        mymsgbuf.types = 100; //给消息结构赋值
    
        key = ftok("./app",'a');  //建立key值
        if(key < 0)
        {
            perror("ftok fail ");
            exit(1);
        }
    
        // 创建消息队列,如果消息队列存在,errno 会提示 eexist
        // 错误,此时只需要直接打开消息队列即可
        msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
        if(msgid < 0)
        {
            if(errno == EEXIST) //文件存在错误提示
            {
                msgid = msgget(key,0666);//打开消息队列
            }
            else //其他错误退出
            {
                perror("msgget fail ");
                exit(1);
            }
        }
    
        while(1)  //接收到 “quit” 结束循环
        {
            //接收消息
            msgrcv(msgid,&recvbuf,sizeof(mymsgbuf)-sizeof(long),100,0); //recvbuf 是接收消息的结构体,其中的b是实际的数据
            if(strstr(recvbuf.b, "quit") != NULL)
            {
                break;
            }
            printf("recvbuf: %s", recvbuf.b); //
        }
    
        //删除消息队列
        msgctl(msgid, IPC_RMID, NULL);
    
        return 0;
    }

    测试:

     

    转载于:https://www.cnblogs.com/electronic/p/10946501.html

    展开全文
  • 实验六进程间通信 实验目的 学会进程间通信方式无名管道有名管道信号消息队列 实验要求 在父进程中创建一无名管道并创建子进程来读该管道父进程来写该管道 在进程中为 SIGBUS注册处理函数并向该进程发送 SIGBUS信号 ...
  • 进程间通信——消息队列

    千次阅读 2018-04-15 18:40:38
    进程间通信——共享内存https://blog.csdn.net/q496958148/article/details/79953349 进程间通信——信号量https://blog.csdn.net/q496958148/article/details/79977093 进程间通信——管 道...

    进程间的通信——共享内存https://blog.csdn.net/q496958148/article/details/79953349
    进程间的通信——信号量https://blog.csdn.net/q496958148/article/details/79977093
    进程间的通信——管 道https://blog.csdn.net/q496958148/article/etails/79948367

    什么是消息队列?

    消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。也就是说进程的退出,如果不自主去释放资源,消息队列是会悄无声息的存在的。消息队列与管道不同的是,消息队列是基于消息的, 而管道是基于字节流的,且消息队列的读取不一定是先入先出。消息队列与命名管道有一 样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限

    进程通信我们有了管道,为什么还要引入消息队列呢?

    因为根据管道的特性,我们知道其在一定程度上存在或多或少的局限性,首先匿名管道以及命名管道是随进程的,进程的退出,意味着管道生命周期的结束;其次,管道传送数据时以无格式字节流的形式传送,这有时会给程序的开发带来不便;再者,担当数据传送媒介的管道,其缓冲区的大小也有较大的限制。所以作为IPC方式下的另一种应用于进程间通信的消息队列方式便应运而生了。
    IPC对象数据结构:

    //内核为每个IPC对象维护了一个数据结构
    struct ipc_perm
    {
        __kernel_key_t  key;//key值是消息队列的一个验证码(我理解为暗号,首先一个进程要向消息队列放入一个东西,得先生成一个key值,这个key值是函数计算得来的,输入值确定会固定得到一个key值,而又有一个进程需要取刚才进程放的东西,这时候就得暗号匹配才能取。)
        __kernel_uid_t  uid;
        __kernel_gid_t  gid;
        __kernel_uid_t  cuid;
        __kernel_gid_t  cgid;
        __kernel_mode_t mode; //权限
        unsigned short  seq;
    };

    消息队列结构:

    struct msqid_ds {
        struct ipc_perm msg_perm;
        struct msg *msg_first;      /* first message on queue,unused  */
        struct msg *msg_last;       /* last message in queue,unused */
        __kernel_time_t msg_stime;  /* last msgsnd time */
        __kernel_time_t msg_rtime;  /* last msgrcv time */
        __kernel_time_t msg_ctime;  /* last change time */
        unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */
        unsigned long  msg_lqbytes; /* ditto */
        unsigned short msg_cbytes;  /* current number of bytes on queue */
        unsigned short msg_qnum;    /* number of messages in queue */
        unsigned short msg_qbytes;  /* max number of bytes on queue */
        __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
        __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
    };
    

    和消息队列有关的函数:

    • 生成key值
    key_t ftok(const char *pathname, int proj_id);
    • 用来创建或者访问一个消息队列
    int msgget(key_t key, int msgflg);
    //key 上面解释过了,相当于一个暗号由ftok函数创建
    //msgflg: IPC_CREAT:创建新的消息队列。 IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。 IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。
    //返回值: 调用成功返回队列标识符,否则返回-1.
    • 消息队列的控制函数
     int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    //msqid:有msgget返回的标识码
    //cmd:将要采取的动作,IPC_STAT把msqid_ds结构的数据设置为消息队列的当前关联值, IPC_SET在权限允许的情况下,吧消息队列的当前关联值设置为msqid_ds数据结构中给出的值,IPC_RMID删除消息队列
    • 插入一条消息到消息队列
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    //msqid:由msgget函数返回的消息队列标识码
    //msgp:指向准备发送消息的指针
    //msgsz:是msgp的长度
    //msgflg:控制这当前消息队列是否满或者达到系统上限
    //返回值成功为0;失败为-1
    • 从消息队列接收一个消息
    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
    //msqid:由msgget函数返回的消息队列标识码
    //msgp:指向准备接收消息的指针
    //msgsz:是msgp的长度
    //msgtyp:它可以实现接收优先级的简单形式
    //msgflg:控制这当前消息队列是否满或者达到系统上限
    //返回值成功为实际接收到接收缓存区的字符个数;失败为-1

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

    实例:
    功能是实现俩个窗口之间的相互通信:
    最终的成果图
    这里写图片描述

    具体实现如下:

    这里写图片描述

    这里写图片描述

    msgges.h:

    #pragma once
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <string.h>
    
    //这俩个宏定义是生成key值
    #define PATH "."
    #define NUM 0x6666
    
    //
    #define SERVER_TYPE 1
    #define CLIENT_TYPE 2
    
    //消息队列中消息的结构体
    struct msgbuf{
        long mtype;//上面进行宏定义的SERVER_TYPE与CLINENT_TYPE就是这个
        char mtext[1024];
    };
    
    int createMsgQueue();
    
    int getMsgQueut();
    
    int destroyMsgQueut(int msgid);
    
    int sendMsg(int msgid,int who,char *msg);
    
    int recvMsg(int msgid,int recvType,char out[]);
    

    msgges.c:

    #include "msgges.h"
    
    //创建一个消息队列,如果已经有了,返回错误
    int createMsgQueue()
    {
        key_t key = ftok(PATH,NUM);//生成key值(暗号)
        if(key < 0)
        {
            perror("ftok");
            return -1;
        }
        int msgid = msgget(key, IPC_CREAT|IPC_EXCL|0666);
        if(msgid < 0)
        {
            perror("msgget");
            return -1;
        }
        return msgid;
    }
    
    //创建一个消息队列,如果已经有消息队列了,返回已经有的消息队列msgid
    int getMsgQueue()
    {
        key_t key = ftok(PATH,NUM);
        if(key < 0)
        {
            perror("ftok");
            return -1;
        }
        int msgid = msgget(key, IPC_CREAT);
        if(msgid < 0)
        {
            perror("msgget");
            return -1;
        }
        return msgid;
    }
    
    //删除消息队列
    int destroyMsgQueue(int msgid)
    {
        printf("111\n");
        if(msgctl(msgid,IPC_RMID,NULL) < 0)
        {
            perror("msgctl");
            return -1;
        }
        return 0;
    }
    
    //往消息队列里发数据
    int sendMsg(int msgid,int who,char *msg)
    {
       struct msgbuf buf;
       buf.mtype = who;
       strcpy(buf.mtext,msg);
    
       if(msgsnd(msgid,(void*)&buf,sizeof(buf.mtext),0) < 0)
       {
           perror("msgsnd");
           return -1;
       }
       return 0;
    }
    
    //从消息队列里取数据
    int recvMsg(int msgid,int recvType, char out[])
    {
        struct msgbuf buf;
        if(msgrcv(msgid,(void*)&buf,sizeof(buf.mtext),recvType,0) < 0)
        {
            perror("msgrcv");
            return -1;
        }
        strcpy(out,buf.mtext);
        return 0;
    }
    

    server.c:

    #include "msgges.h"
    
    int main()
    {
        int msgid = createMsgQueue();
        char buf[1024];
        while(1)
        {
            buf[0] = 0;
            recvMsg(msgid,CLIENT_TYPE,buf);
            printf("小明:%s\n",buf);
    
            printf("你:");
            fflush(stdout);
            ssize_t s = read(0,buf,sizeof(buf));
            if(s > 0)
            {
                buf[s-1] = 0;
                sendMsg(msgid,SERVER_TYPE,buf);
            }
        }
        destroyMsgQueue(msgid);
        return 0;
    }
    

    client.c:

    #include "msgges.h"
    
    int main()
    {
        int msgid = getMsgQueue();
        char buf[1024];
    
        while(1)
        {
            buf[0] = 0;
            printf("你:");
            fflush(stdout);
            ssize_t s = read(0,buf,sizeof(buf));
            if(s > 0)
            {
                buf[s-1] = 0;
                sendMsg(msgid,CLIENT_TYPE,buf);
            }
    
            recvMsg(msgid,SERVER_TYPE,buf);
            printf("张三:%s\n",buf);
        }
        return 0;
    }
    

    Makefile:

    .PHONY:all
    all:client server
    
    
    client:client.c msgges.c
        gcc $^ -o $@;
    server:server.c msgges.c
        gcc $^ -o $@;
    
    
    .PHONY:clean
    clean:
        rm -f client server

    最后如果你出现了下面的错误:
    这里写图片描述
    解决办法如下:
    这里写图片描述
    造成这个原因是,你只要编译通过,并且运行了 你再用ctrl+c 终止掉进程,进程不会走这个函数的destroyMsgQueue(msgid); 一旦你发出ctrl+c信号,操作系统就会马上杀死该进程。这样就会造成IPC没有及时被回收。想要解决这个问题我们可以将ctrl+c 的执行函数改为destroyMsgQueue(msgid); 并且执行完后退出即可。

    展开全文
  • linux 进程间通信消息队列以及实例 消息可以理解为写信给某个人,这里在应用中是告诉系统写信人和写信的内容就可以了, 别人会来看发信人是谁,如果不是自己想要的就放弃读信或者只要有消息自己就读取消息 ...
  • 进程间通信方式总结——消息队列

    千次阅读 2017-04-16 11:52:25
    Linux/Unix系统IPC是各种进程间通信方式的统称,...一般来说,Linux/Unix常见的进程间通信方式有:管道、消息队列、信号、信号量、共享内存、套接字等。博主将在《进程间通信方式总结》系列博文中和大家一起探讨学习进
  • 进程间通信 —IPC(InterProcess Communication) 进程间通信是不同的进程通过一个或多个文件来传递信息。经常用到的通信方式有两种,一种是通过管道来实现两个进程间的通信,管道机制是创建的不同进程通过调用管道...
  • 消息队列允许一个或多个进程向它写入与读取消息.  3.管道和命名管道都是通信数据都是先进先出的原则。  4.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更...
  • C#进程间通信的几种方式:消息队列

    千次阅读 2019-03-07 17:09:11
    消息”是在两台计算机传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中。消息队列(Message Queue)是在消息的传输过程中保存消息的容器。消息...
  • C#进程间通信-消息队列代码实例。用实现了2个进程,他们之间使用消息队列方式进行通信。
  • #使用队列,将消息写进队列,需要的进程队列取 #队列由父进程创建,子进程共享队列 def write(qe): print("启动子进程 write") for chr in ['A','B','C','D','E']: qe.put(chr) time.sleep(1)...
  • Linux进程间通信——使用消息队列

    万次阅读 多人点赞 2013-08-25 00:09:57
    下面来说说如何用不用消息队列来进行进程间通信消息队列与命名管道有很多相似之处。 一、什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,...
  • Linux进程间通信——消息队列 Linux提供了多种进程间通信的方法,常见有管道(匿名)、FIFO(有名管道)、消息队列、信号量、共享内存,socket通信。 3.消息队列 消息队列提供了一种从一个进程向另一个进程发送一个...
  • 利用消息队列基本函数,实现Linux系统下进程A和进程B之间的消息收发。 msgsend输入‘end’,退出程序
  • 使用消息队列进行进程间通信(代码实例)
  •  进程间基于消息队列通信 2[实验目的]  系统了解linux系统的通信机构IPC ,掌握IPC中消息通信机制,理解消息通信的方法及特征。 3[实验内容]  编写一段程序,同时父进程创建两个子进程p1和p2;并使子进程...
  • 关于Linux系统进程通信的概念及实现可查看:...我们需要利用sysvmsg模块提供的函数来进进程间通信。先来看一段示例代码_1: 复制代码 代码如下: <?php $message_queue_key = ftok(__
  • 发送端代码: /*************************************************** ##filename : msggetS.c ##author : GYZ ##e-mail : 1746902011@qq.com ##cr...
  • 操作系统课程实验报告 实习题目 进程间基于消息队列通信 指导教 学生姓名 学 号 日 期 实现工具 C 语言 实现环境 Linux 系统 实验目的 系统了解linux 系统的通信机构IPC 掌握IPC 中消息通信机 制理解消息通信的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,368
精华内容 45,747
关键字:

进程间通信消息队列