进程间通信:消息队列

http://blog.csdn.net/ljianhui/article/details/10287879

#include <sys/type.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int flag);
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
int msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
int msgctl(int msqid, int cmd, struct mspid_ds *buf);

int msgget(key_t key, int flag);

msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。它返回一个以key命名的消息队列的标识符(非零整数),失败时返回-1.

int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);

int msgrcv(int msqid, void *ptr, size_t nbytes, long msgtype, int flag);

msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。

flag取值包括0(阻塞)和IPC_NOWAIT(如果消息队列为空,则返回一个ENOMSG)

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

cmd是将要采取的动作,它可以取3个值,

IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。

IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值

IPC_RMID:删除消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>

/*

#include <sys/type.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int flag);
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
int msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
int msgctl(int msqid, int cmd, struct mspid_ds *buf);

*/

#ifndef T_DESC
#define T_DESC(x, y)   (y)
#endif

#if T_DESC("TU1", 1)

int msg_qid;

typedef struct msgbuf
    {
        long msgtype;
        char msgtext[128];
    } PRIV_MSG_INFO;

int send_task(void)
{
    PRIV_MSG_INFO sndmsg;

    for(;;)
    {
        sndmsg.msgtype++;
        sprintf(sndmsg.msgtext, "type %ld", sndmsg.msgtype);
        if(msgsnd(msg_qid, (PRIV_MSG_INFO *)&sndmsg, sizeof(PRIV_MSG_INFO), 0)==-1)
        {
            printf("msgsnd error\n");
            exit(254);
        }
        sleep(3);
    }
}

int recv_task(void)
{
    PRIV_MSG_INFO rcvmsg;

    for(;;)
    {
        if(msgrcv(msg_qid, (PRIV_MSG_INFO *)&rcvmsg, sizeof(PRIV_MSG_INFO), 0, 0) == -1)
        {
            printf("msgsnd error\n");
            exit(254);
        }
        printf("recv msg: %s\n", rcvmsg.msgtext);
    }
}

int tu1_proc(void)
{
    pthread_t id_1,id_2;
    int i,ret;  

    msg_qid = msgget(IPC_PRIVATE, 0666);
    if(msg_qid == -1)
    {
        printf("msgget error\n");
        exit(254);
    }

    ret = pthread_create(&id_1, NULL, (void *)send_task, NULL);
    if(ret != 0)
    {
        printf("Create pthread error!\n");
        return -1;
    }  

    ret = pthread_create(&id_2, NULL, (void *)recv_task, NULL);
    if(ret != 0)
    {
        printf("Create pthread error!\n");
        return -1;
    }  

    /*μè′y??3ì?áê?*/
    pthread_join(id_1, NULL);
    pthread_join(id_2, NULL);  

    msgctl(msg_qid, IPC_RMID, 0);

    return 0;
}  

#endif

#if T_DESC("TU2", 1)

int send_task2(void)
{
    PRIV_MSG_INFO sndmsg;

    msg_qid = msgget((key_t)1234, 0666 | IPC_CREAT);
    if(msg_qid == -1)
    {
        printf("msgget error\n");
        exit(254);
    }

    for(;;)
    {
        sndmsg.msgtype=10;
        sprintf(sndmsg.msgtext, "type %ld", sndmsg.msgtype);
        if(msgsnd(msg_qid, (PRIV_MSG_INFO *)&sndmsg, sizeof(PRIV_MSG_INFO), 0)==-1)
        {
            printf("msgsnd error\n");
            exit(254);
        }

        sndmsg.msgtype=20;
        sprintf(sndmsg.msgtext, "type %ld", sndmsg.msgtype);
        if(msgsnd(msg_qid, (PRIV_MSG_INFO *)&sndmsg, sizeof(PRIV_MSG_INFO), 0)==-1)
        {
            printf("msgsnd error\n");
            exit(254);
        }
        sleep(3);
    }
}

int recv_task2(void)
{
    PRIV_MSG_INFO rcvmsg;

    msg_qid = msgget((key_t)1234, 0666 | IPC_CREAT);
    if(msg_qid == -1)
    {
        printf("msgget error\n");
        exit(254);
    }

    for(;;)
    {
        if(msgrcv(msg_qid, (PRIV_MSG_INFO *)&rcvmsg, sizeof(PRIV_MSG_INFO), 10, 0) == -1)
        {
            printf("msgsnd error\n");
            exit(254);
        }
        printf("recv msg: %s\n", rcvmsg.msgtext);
    }
}

int tu2_proc(int argc, char **argv)
{
    pthread_t id_1,id_2;
    int i,ret;
    int param;

    if (argc < 2) return 1;
    param = atoi(argv[1]);

    if (!param) {
        ret = pthread_create(&id_1, NULL, (void *)send_task2, NULL);
    } else {
        ret = pthread_create(&id_2, NULL, (void *)recv_task2, NULL);
    }
    if(ret != 0)
    {
        printf("Create pthread error!\n");
        return -1;
    }  

    /*μè′y??3ì?áê?*/
    if (!param) {
        pthread_join(id_1, NULL);
    } else {
        pthread_join(id_2, NULL);
    }

    return 0;
}  

#endif

#if T_DESC("global", 1)

void usage()
{
    printf("\n Usage: <cmd> <tu> <p1> <...>");
    printf("\n   1 -- msgQ between thread");
    printf("\n   2 -- msgQ between process");
    printf("\n     => P1: 0 - create pid 0; 1 - create pid 1");
    printf("\n");
}

int main(int argc, char **argv)
{
    int ret;

    if(argc < 2) {
        usage();
        return 0;
    }

    int tu = atoi(argv[1]);
    if (tu == 1) ret = tu1_proc();
    if (tu == 2) ret = tu2_proc(argc - 1, &argv[1]);

    return ret;
}
#endif
时间: 2024-12-17 15:12:53

进程间通信:消息队列的相关文章

Linux进程间通信 -- 消息队列 msgget()、msgsend()、msgrcv()、msgctl()

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条

进程间通信——消息队列

1.消息队列的简介 消息队列就是在进程之间架设起通信的通道,信息在通道中传递(具有时间先后的),从宏观逻辑上来讲与管道是一致的.即就是消息队列也同样是:(1).具有入口和出口:(2).消息从入口到出口,是FIFO的:(3).所以消息在其中是队列的存储形式. 消息队列与管道不同的地方在于:管道中的数据并没有分割为一个一个的数据独立单位,在字节流上是连续的.然而,消息队列却将数据分成了一个一个独立的数据单位,每一个数据单位被称为消息体.每一个消息体都是固定大小的存储块儿,在字节流上是不连续的. 2.

Linux进程间通信-消息队列

消息队列是在两个进程之间传递二进制块数据的一种简单有效的方式.每个数据块都有一个特定的类型,接收方可以根据类型来有选择的接收数据,而不一定像管道和匿名管道那样必须以先进先出的方式接收数据. Linux消息队列的4个API包括四个系统调用:msgget.msgsnd.msgcrv和msgctl #include <sys/msg.h> int msgget( key_t key, int msgflg ); int msgsnd( int sigid, const void* msg_ptr,

Linux进程间通信—消息队列

四.消息队列(Message Queue) 消息队列就是消息的一个链表,它允许一个或者多个进程向它写消息,一个或多个进程向它读消息.Linux维护了一个消息队列向量表:msgque,来表示系统中所有的消息队列. 消息队列克服了信号传递信息少,管道只能支持无格式字节流和缓冲区受限的缺点. 消息队列用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中用来保存消息的队列,它在系统内核中是以消息链表的形式出现.消息链表中节点的结构用msg声明. 事实上,它是一种正逐渐被淘汰的通信方式,

详解linux进程间通信-消息队列

前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构(消息队列.信号量或共享存储段)都用一个非负整数的标识符( i d e n t i f i e r )加以引用. 无论何时创建I P C结构(调用m s g g e t. s e m g e t或s h m g e t) ,都应指定一个关键字(k e y),关键字的数据类型由系统规定为 k e y

Linux 进程间通信 消息队列 实现两个进程间通信

例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据 文件1 创建进程1 终端输入通过消息队列发送数据 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <s

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

1. 基本特点 1) 消息队列是一个由系统内核负责存储和管理,并通过消息队列标识引用的数据链表,消息队列 和有名管道fifo的区别在: 后者一次只能放一个包,而前者则可以放很多包,这样就能处理发包快,哪包慢的问题 2) 可以通过msgget函数创建一个新的消息队列, 或获取一个已有的消息队列. 通过msgsnd函数 (send)向消息队列的后端追加消息, 通过msgrcv(receive)函数从消息队列的前端提取消息. 3) 消息队列中的每个消息单元除包含消息数据外,还包含消息类型和数据长度.消

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

一.消息队列的定义 消息队列能够弥补管道的不足,实现双向交互数据,是一个进程向另一进程发送进程块的方法.与管道不同的是,管道是基于字节流的,消息队列是基于消息的,且消息队列的读取不一定是先进先出. 二.消息队列的创建 通过函数int messget(key_t key,int msgflg);创建 key:端口号,可以有 ftok生成. msgflg: IPC_CRTAT 若果 IPC不存在,则创建一个IPC资源, IPC_EXCL:一般和 IPC_CREAT一起使用可以保证所得的对象是新建的,

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

消息队列(报文队列):两个进程间通过发送数据块的形式进行通信.一个进程把需要发送的消息通过一个函数发送到消息队列中,另一个进程再从消息队列中读取该消息. 函数: # include <sys/types.h> # include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); //生成下面函数的key.可认为是一个端口号 int msgget(key_t key, int msgflg);//创建消息队列,返回消

进程间通信(6) - 消息队列posix

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.介绍 消息队列是先进先出FIFO原则. 消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权限的进程则可以从消息队列中读走消息.消息队列是随内核持续的. 目前主要有两种类型的消息队列:POSIX消息队列以及System V消息队列,System V消息队列目前被