精华内容
下载资源
问答
  • linux 消息队列阻塞
    2021-05-18 10:30:34

    消息队列的概念:

    消息队列提供了一种从进程向另一个进程发送一个数据块的方法。每个数据块都被认为是用一个类型,接收者进程接收的数据块可以有不同的类型值。我们可以通过发送消息来避免命名管道的同步和阻塞的问题。消息队列与管道不同的事,消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出。消息队列和命名管道有一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也是有一个上限(MSGMNI)。

    IPC对象数据结构:

    struct ipc_perm

    {

    key_t __key;

    uid_t uid;

    gid_t gid;

    uid_t cuid;

    gid)t cgid;

    unsigned short mode;

    unsigned short short__seq;

    };

    创建新消息队列或取得已存在消息队列:

    int msgget(key_t key,int msgflg)

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

    msgflg:

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

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

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

    如果将IPC_CRETA和IPC_EXCL标志一起使用,XXXget()将返回一个新建的IPC标识符;如果IPC资源存在,则返回-1。

    IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得对象是新建的,而不是打开已有的对象。

    向队列读/写消息:

    读消息:ssize_t magrcv(int msqid,void* msgp,size_t masgsz,long msgtyp,int msgflg);

    写消息:int msgsnd(int msqid,const void* msgp,size_t msgsz,int msgflg);

    参数:

    msgqid:消息队列的标识码;

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

    struct msgstru

    {

    long mytype;//大于0

    char mtext[用户指定大小];

    };

    msgsz:消息的大小;

    msgtyp:从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都会被读取;

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

    设置消息队列的属性:

    int msgctl(int msgqid,int cmd,struct msqid_ds* buf)

    参数:

    msgctl系统调用对msgqid标识的队列消息执行cmd操作,系统定义了3种cmd操作:IPC_STAT,IPC_SET,IPC_RMID

    IPC_STAT:该命令用来获取消息队列对应的msgqid_ds数据结构,并将其保存到buf指定的地址空间。

    IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf中。

    IPC_RMID:从内核中删除msgqid标识的消息队列。

    ftok函数:把一个已存在的路径名和一个整数标识转换成一个key_t值,称为IPC键。

    key_t ftok(const char* pathname,int proj_id)

    ftok的典型实现调用stat函数,然后组合一下三个值:

    1、pathname所在的文件系统的信息(stat结构的st_dev成员);

    2、该文件在本文系统内的索引节点号(stat结构的st_ino成员)

    3、proj_id的低序8位(不能为0)

    不能保证两个不同的路径名与同一个proj_id的组合产生不同的键,因为上面所列三个条目(文件系统标识符、索引节点、proj_id)中的信息位数可能大于一个整数的信息位数。

    更多相关内容
  • 一、消息队列的特点1.消息队列消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识.2.消息队列允许一个或多个进程向它写入与读取消息.3.管道和命名管道都是通信数据都是先进先出的原则。4.消息队列可以...

    一、消息队列的特点

    1.消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识.

    2.消息队列允许一个或多个进程向它写入与读取消息.

    3.管道和命名管道都是通信数据都是先进先出的原则。

    4.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更有优势。

    目前主要有两种类型的消息队列:POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用。系统V消息队列是随内核持续的,只有在内核重起或者人工删除时,该消息队列才会被删除。

    二、相关函数

    1. 获得key值

    key_t ftok(char *pathname, int projid)

    #include

    #include

    参数:

    pathname:文件名(含路径),通常设置为当前目录“.”

    projid:项目ID,必须为非0整数(0-255).

    2. 创建消息队列

    int msgget(key_t key, int msgflag)

    #include

    #include

    #include

    功能:

    用于创建一个新的或打开一个已经存在的消息队列,此消息队列与key相对应。

    参数:

    key:函数ftok的返回值或IPC_PRIVATE。

    msgflag:

    IPC_CREAT:创建新的消息队列。

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

    IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。

    返回值:

    调用成功返回队列标识符,否则返回-1.

    在以下两种情况下,将创建一个新的消息队列:

    1、如果没有与键值key相对应的消息队列,并且msgflag中包含了IPC_CREAT标志位。

    2、key参数为IPC_PRIVATE。

    3. 消息队列属性控制

    int msgctl(int msqid,  int cmd,  struct msqid_ds *buf)

    功能:

    对消息队列进行各种控制操作,操作的动作由cmd控制。

    参数:

    msqid:消息队列ID,消息队列标识符,该值为msgget创建消息队列的返回值。

    cmd:

    IPC_STAT:将msqid相关的数据结构中各个元素的当前值存入到由buf指向的结构中.

    IPC_SET:将msqid相关的数据结构中的元素设置为由buf指向的结构中的对应值.

    IPC_RMID:删除由msqid指示的消息队列,将它从系统中删除并破坏相关数据结构.

    buf:消息队列缓冲区

    struct msqid_ds {

    struct ipc_perm msg_perm;          /* Ownership and permissions*/

    time_t        msg_stime;                /* Time of last msgsnd() */

    time_t        msg_rtime;                  /* Time of last msgrcv() */

    time_t        msg_ctime;                /* Time of last change */

    unsigned long  __msg_cbytes;    /* Current number of bytes in  queue (non-standard) */

    msgqnum_t      msg_qnum;          /* Current number of messages  in queue */

    msglen_t      msg_qbytes;          /* Maximum number of bytesallowed in queue */

    pid_t          msg_lspid;                  /* PID of last msgsnd() */

    pid_t          msg_lrpid;                  /* PID of last msgrcv() */

    };

    struct ipc_perm {

    key_t key;                        /* Key supplied to msgget() */

    uid_t uid;                        /* Effective UID of owner */

    gid_t gid;                        /* Effective GID of owner */

    uid_t cuid;                      /* Effective UID of creator */

    gid_t cgid;                      /* Effective GID of creator */

    unsigned short mode;    /* Permissions */

    unsigned short seq;      /* Sequence number */

    };

    4.发送信息到消息队列

    int msgsnd(int msqid,  struct msgbuf *msgp,  size_t msgsz,  int msgflag)

    #include

    #include

    #include

    功能:

    将新消息添加到队列尾端,即向消息队列中发送一条消息。

    参数:

    msqid:已打开的消息队列id

    msgp:存放消息的结构体指针。

    msgflag:函数的控制属性。

    消息结构msgbuf为:

    struct msgbuf

    {

    long mtype;//消息类型

    char mtext[1];//消息正文,消息数据的首地址

    }

    msgsz:消息数据的长度。

    msgflag:

    IPC_NOWAIT: 指明在消息队列没有足够空间容纳要发送的消息时,msgsnd立即返回。

    0:msgsnd调用阻塞直到条件满足为止.(一般选这个)

    5. 从消息队列接收信息

    ssize_t msgrcv(int msqid,  struct msgbuf *msgp,  size_t msgsz,  long msgtype,  int msgflag)

    #include

    #include

    #include

    21/212>

    展开全文
  • Linux下的线程通信没有像RTOS下支持阻塞消息队列。想要支持阻塞消息队列就要自己实现了。 实现可阻塞消息队列需要用到pthread中的条件变量(pthread_cond_t )和互斥锁(pthread_mutex_t )。 数据结构 #define ...

    消息队列

    消息队列实现并不难。消息队列主要有两种实现方式:数组实现和链表实现。
    此处采用链表实现。由于实现并不能难,重写浪费时间,直接参考别人的就好了。

    Linux下消息队列实现

    Linux下的同个进程的线程通信好像没有RTOS下支持阻塞的消息队列。想要支持阻塞的消息队列似乎就要自己实现了。
    实现可阻塞的消息队列需要用到pthread中的条件变量(pthread_cond_t )互斥锁(pthread_mutex_t )

    数据结构

    #define LIN_MSG_MAX_LEN    4096      /* max 4K */
    
    /* msgqueue return state */
    #define LIN_MSGQ_EOK     0          /**< There is no error */                
    #define LIN_MSGQ_ERROR   1           /**< A generic error happens */
    #define LIN_MSGQ_EINVAL  2           /**< Invalid argument */
    #define LIN_MSGQ_ENOMEM  3            /**< No memory */
    #define LIN_MSGQ_TIMEOUT 4            /**< Timeout> */
    
    struct lin_msgq_block;
    typedef struct lin_msgq_block lin_mq_blk_t;
    
    /* message block */
    struct lin_msgq_block {
        lin_mq_blk_t *next;  
    	int len;
        char *data;
    };
      
    struct lin_msgqueue;
    typedef struct lin_msgqueue lin_mq_t;
    
    struct lin_msgqueue
    {
        lin_mq_blk_t *first;
        lin_mq_blk_t *last;
        int     num;
     
        pthread_mutex_t mutex;
        pthread_cond_t  not_empty;
    };
    

    消息队列的API接口

    lin_mq_t *lin_mq_create(void); 
    int lin_mq_destroy(lin_mq_t *mq);
    int lin_mq_send_msg(lin_mq_t *mq, char *msg, int msg_len);
    int lin_mq_get_msg(lin_mq_t *mq, char *buffer, int size);
    int lin_mq_get_msg_timeout(lin_mq_t *mq, char *buffer, int size, int timeout);
    int lin_mq_get_msg_num(lin_mq_t *mq);
    int lin_mq_clear(lin_mq_t *mq);
    

    消息队列API接口实现

    #define SLOG_USE_CUSTOM   1
    
    #if SLOG_USE_CUSTOM == 1
    #define _PRINT   printf
    #else
    #define _PRINT 
    #endif
     
    #define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1) : __FILE__)
    
    #define SLOG_PRINT(X, args...) _PRINT("[%s]-%d:" X, __FILENAME__, __LINE__, ##args)
    
    static unsigned long long timeout_ns = 0;
    
    static void lin_mq_free_msg_blk(lin_mq_blk_t *elm)
    {
        if (elm != NULL)
        {
            if (elm->data != NULL)
            {
                free(elm->data);
                elm->data = NULL;
            }
            free(elm);
            elm = NULL;
        }
    }
    
    static void put_msg_to_queue(lin_mq_t *mq, lin_mq_blk_t *elm)
    {
        if (NULL == mq || NULL == elm)
        {
            SLOG_PRINT("mq or elm is NULL");
            return;
        }
    
        if (NULL != elm->next)
        {
            elm->next = NULL;
        }
    
        pthread_mutex_lock(&mq->mutex);
        /* message queue have no message block */
        if (mq->first == mq->last && 0 == mq->num)
        {
            mq->first = elm;
            mq->last = elm;
            mq->num++;
            /* There is a new message block, Wake up a blocked thread */
            pthread_cond_signal(&mq->not_empty);
        }
        else
        {
            /* Insert the new message block at the end of the queue */
            mq->last->next = elm;
            mq->last = elm;
            mq->num++;
        }
    
        pthread_mutex_unlock(&mq->mutex);
    }
    
    static int lin_mq_get_msg_blk(lin_mq_t *mq, lin_mq_blk_t **blk)
    {
        if (NULL == mq)
        {
            SLOG_PRINT("mq or elm is NULL");
            return -LIN_MSGQ_EINVAL;
        }
    
        pthread_mutex_lock(&mq->mutex);
        /* message queue have no message block */
        while (0 == mq->num)
        {
            /* blocking threads and wait message block */
            pthread_cond_wait(&mq->not_empty, &mq->mutex);
        }
        /* get new message block from message queue */
        *blk = (mq->first);
        if (1 == mq->num)
        {
            mq->first = mq->last = NULL;
            mq->num = 0;
        }
        else
        {
            mq->first = mq->first->next;
            mq->num--;
        }
    
        pthread_mutex_unlock(&mq->mutex);
    
        return LIN_MSGQ_EOK;
    }
    
    int lin_mq_get_msg(lin_mq_t *mq, char *buffer, int size)
    {
        int ret;
        lin_mq_blk_t *blk;
        ret = lin_mq_get_msg_blk(mq, &blk);  
        if (ret != LIN_MSGQ_EOK) return ret;
    
        if (blk->data != NULL)
        {
            size = size > blk->len ? blk->len : size;
            memmove(buffer, blk->data, size);
            lin_mq_free_msg_blk(blk);
        }
        return LIN_MSGQ_EOK;
    }
    
    static int lin_mq_get_msg_blk_timeout(lin_mq_t *mq, lin_mq_blk_t **blk, int timeout)
    {
        struct timespec timenow;
    
        if (NULL == mq)
        {
            SLOG_PRINT("mq or elm is NULL");
            return -LIN_MSGQ_EINVAL;
        }
    
        pthread_mutex_lock(&mq->mutex);
        /* There is no message block */
        if (0 == mq->num)
        {
            clock_gettime(CLOCK_MONOTONIC, &timenow);
            timenow.tv_sec = timenow.tv_sec + timeout / 1000; /* add sec */
            timeout %= 1000;                                  /* get msec */
    
            timeout_ns = timenow.tv_nsec + timeout * 1000 * 1000;  /* get nsec */
            /* If more than 1 s */
            if (timeout_ns >= 1000 * 1000 * 1000) 
            {
                timenow.tv_sec++;
                timenow.tv_nsec = timeout_ns - 1000 * 1000 * 1000;
            }
            else
                timenow.tv_nsec = timeout_ns;
    
            /* blocking threads and wait timeout */
            pthread_cond_timedwait(&mq->not_empty, &mq->mutex, &timenow);
        }
    
        if (mq->num <= 0)
        {   
            pthread_mutex_unlock(&mq->mutex);
            return -LIN_MSGQ_TIMEOUT;
        }
    
        /* get the message block from the message queue head */
        *blk = mq->first;
        if (1 == mq->num)
        {
            mq->first = mq->last = NULL;
            mq->num = 0;
        }
        else
        {
            mq->first = mq->first->next;
            mq->num--;
        }
    
        pthread_mutex_unlock(&mq->mutex);
    
        return LIN_MSGQ_EOK;
    }
    
    int lin_mq_get_msg_timeout(lin_mq_t *mq, char *buffer, int size, int timeout)
    {
        int ret;
        lin_mq_blk_t *blk = NULL;
    
        ret = lin_mq_get_msg_blk_timeout(mq, &blk, timeout);  
        if (ret != LIN_MSGQ_EOK) return ret;
    
        if (blk->data == NULL)
        {
            SLOG_PRINT("message block data is NULL\r\n");
            return -LIN_MSGQ_ENOMEM;
        }
    
        size = size > blk->len ? blk->len : size;
        memmove(buffer, blk->data, size);
        lin_mq_free_msg_blk(blk);
        return LIN_MSGQ_EOK;
    }
    
    int lin_mq_clear(lin_mq_t *mq)
    {
        lin_mq_blk_t *blk = NULL;
        lin_mq_blk_t *blk_tmp = NULL;
    
        if (NULL == mq)
        {
            SLOG_PRINT("mq is NULL");
            return -LIN_MSGQ_EINVAL;
        }
    
        if (mq->num <= 0)
        {
            SLOG_PRINT("mq->num is 0\r\n");
            return -LIN_MSGQ_ERROR;
        }
    
        pthread_mutex_lock(&mq->mutex);
        /* Clears all message nodes in the buffer before the current message node */
        blk = mq->first;
        while (blk != NULL)
        {
            if (blk == mq->last)
            {
                mq->first = mq->last;
                if (mq->num != 1)
                {
                    mq->num = 1;
                }
                break;
            }
    
            blk_tmp = blk->next;
            lin_mq_free_msg_blk(blk);
            mq->num--;
            blk = blk_tmp;
            mq->first = blk;
        }
    
        pthread_mutex_unlock(&mq->mutex);
    
        return LIN_MSGQ_EOK;
    }
    
    int lin_mq_send_msg(lin_mq_t *mq, char *msg, int msg_len)
    {
        lin_mq_blk_t *blk = NULL;
    
        if (msg == NULL) 
        {
            SLOG_PRINT("msg is NULL!!!");
            return -LIN_MSGQ_EINVAL;
        }
    
        blk = (lin_mq_blk_t *)malloc(sizeof(lin_mq_blk_t));
        if (NULL == blk)
        {
            SLOG_PRINT("new msg element failed!!");
            return -LIN_MSGQ_ENOMEM;
        }
        /* Limit maximum length */
        if (msg_len > LIN_MSG_MAX_LEN) 
        {
            msg_len = LIN_MSG_MAX_LEN;
            SLOG_PRINT("msg %d!", LIN_MSG_MAX_LEN);
        }
    
        memset(blk, 0, sizeof(lin_mq_blk_t));
        blk->len = msg_len;
        /* Allocate memory based on the sent size */
        blk->data = (char *)malloc(msg_len); 
        if (blk->data == NULL)
        {
            SLOG_PRINT("new element->data failed!!");
            lin_mq_free_msg_blk(blk);
            return -LIN_MSGQ_ENOMEM;
        }
    
        memmove(blk->data, msg, msg_len);
    
        blk->next = NULL;
    
        put_msg_to_queue(mq, blk);
    
        return LIN_MSGQ_EOK;
    }
    
    int lin_mq_destroy(lin_mq_t *mq)
    {
        lin_mq_blk_t *blk = NULL;
    
        if (NULL == mq)
        {
            return (-LIN_MSGQ_EINVAL);
        }
    
        if (mq->first != mq->last && mq->num > 0)
        {
            blk = lin_mq_clear(mq);
        }
        else
        {
            blk = mq->last;
        }
    
        if (NULL != blk)
        {
            lin_mq_free_msg_blk(blk);
            mq->first = mq->last = NULL;
            mq->num = 0;
        }
    
        pthread_mutex_destroy(&mq->mutex);
        pthread_cond_destroy(&mq->not_empty);
        free(mq);
    
        mq = NULL;
        return (LIN_MSGQ_EOK);
    }
    
    int lin_mq_get_msg_num(lin_mq_t *mq)
    {
        if (NULL == mq)
            return (-LIN_MSGQ_EINVAL);
    
        return mq->num;
    }
    
    
    lin_mq_t *lin_mq_create(void)
    {
        lin_mq_t *mq = NULL;
        pthread_condattr_t cattr;
    
        mq = (lin_mq_t *)malloc(sizeof(lin_mq_t));
        if (NULL == mq)
        {
            SLOG_PRINT("init msg buffer failed!!");
            return NULL;
        }
    
        memset(mq, 0, sizeof(lin_mq_t));
        mq->first = NULL;
        mq->last = NULL;
        mq->num = 0;
    
        pthread_mutex_init(&(mq->mutex), NULL);
    #if 1
        pthread_condattr_init(&cattr);
        pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
        pthread_cond_init(&(mq->not_empty), &cattr);
    #else
        pthread_cond_init(&(mq->not_empty), NULL);
    #endif
    
        return mq;
    }
    

    测试

    代码:https://gitee.com/guangjieMVP/lin_msgqueue.git

    安装xmake
    sudo add-apt-repository ppa:xmake-io/xmake
    sudo apt update
    sudo apt install xmake
    

    查看是否安装成功:

    xmake --version
    
    编译
    xmake
    
    执行
    ./build/linux/x86_64/debug/linqueue_test
    
    展开全文
  • Linux消息队列编程

    2022-03-10 14:04:19
    Linux消息队列编程(简单应用) 消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。可以解决两个进程的读写速度不同...

    Linux消息队列编程(简单应用)

    消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。可以解决两个进程的读写速度不同(处理数据速度不同),系统耦合等问题,而且消息队列里的消息哪怕进程崩溃了也不会消失。

    最简单的消息内存的使用流程

    ①ftok函数生成键值

    ②msgget函数创建消息队列

    ③msgsnd函数往消息队列发送消息

    ④msgrcv函数从消息队列读取消息

    ⑤msgctl函数进行删除消息队列

    一个消息数据应该由以下一个结构体组成,举个例子

    struct mymesg{
    long int mtype;	//类,消息队列可以控制读取相应类型的数据,这时就不一定是先进先出的顺序了,文章后面会继续介绍
    char mtext[size_t];	//数据,传递的数据存放在这里面
    };
    

    1.ftok函数生成键值

    每一个消息队列都有一个对应的键值(key)相关联(共享内存、信号量也同样需要)。

    所需头文件#include<sys/ipc.h>

    函数原型 key_t ftok(const char *path ,int id);

    path为一个已存在的路径名

    id为0~255之间的一个数值,代表项目ID,自己取

    返回值:成功返回键值(相当于32位的int)。出错返回-1

    例如:key_t key = ftok( “/tmp”, 66);

    2.msgget函数创建消息队列

    所需头文件#include<sys/msg.h>

    函数原型 int msgget(key_t key,int flag);

    key为ftok生成的键值

    flag为所需要的操作和权限,可以用来控制创建一个消息队列。

    flag的值为IPC_CREAT:如果不存在key值的消息队列,且权限不为0,则创建消息队列,并返回一个消息队列ID。如果存在,则直接返回消息队列ID。

    flag的值为 IPC_CREAT | IPC_EXCL:如果不存在key值的消息队列,且权限不为0,则创建消息队列,并返回一个消息队列ID。如果存在,则产生错误。

    返回值:成功返回消息队列ID;出错返回-1

    例如:int id = msgget(key,IPC_CREAT|IPC_EXCL|0666);创建一个权限为0666(所有用户可读可写,具体查询linux权限相关内容)的消息队列,并返回一个整形消息队列ID,如果key值已经存在有消息队列了,则出错返回-1。

    int id = msgget(key,IPC_CREAT|0666);创建一个权限为0666(所有用户可读可写,具体查询linux权限相关内容)的消息队列,并返回一个消息队列ID,如果key值已经存在有消息队列了,则直接返回一个消息队列ID。

    3.msgsnd函数往消息队列发送消息

    所需头文件#include<sys/msg.h>

    函数原型 int msgsnd(int msgid,const void *ptr,size_t nbytes,int flag);
    msgid:为msgget返回的消息队列ID值
    ptr:为消息结构体mymesg指针
    nbytes:为消息结构体mymesg里的字符数组mtext大小,sizeof(mtext)
    flag:值可以为0、IPC_NOWAIT
    为0时,当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列或者消息队列被删除。
    为IPC_NOWAIT时,当消息队列满了,msgsnd函数将不会等待,会立即出错返回EAGAIN

    **返回值:**成功返回0;错误返回-1

    **例如:**msgsnd(id,(void *)&ckxmsg,512,0);

    4.msgrcv函数从消息队列读取消息

    所需头文件#include<sys/msg.h>

    函数原型 ssize_t msgrcv(int msgid,void *ptr,size_t nbytes,long type,int flag);

    msgid:为msgget返回的消息队列ID值

    ptr:为消息结构体mymesg指针

    nbytes:为消息结构体mymesg里的字符数组mtext大小,sizeof(mtext)

    type:在结构体mymesg里我们定义了一个long int mtype,用于分别消息的类型

    type ==0 返回队列中的第一个消息

    type > 0 返回队列中消息类型为type的第一个消息

    type < 0 返回队列中消息类型值小于等于type绝对值的消息,如果这种消息有若干个,则取类型值最小的消息

    flag:可以为0、IPC_NOWAIT、IPC_EXCEPT

    为0时,阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待

    为IPC_NOWAIT时,如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG

    为IPC_EXCEPT时,与msgtype配合使用返回队列中第一个类型不为msgtype的消息

    返回值:成功返回消息数据部分的长度;错误返回-1

    例如:msgrcv(id,(void *)&ckxmsg,512,1,0);

    5.msgctl函数对消息队列进行控制

    简单的操作就是删除消息队列了,也可以获取和改变消息队列的状态

    所需头文件#include<sys/msg.h>

    函数原型int msgctl(int msgid, int cmd, struct msqid_ds *buf);

    msgid就是msgget函数返回的消息队列ID

    cmd有三个,常用删除消息队列的为IPC_RMID;IPC_STAT:取此队列的msqid_ds结构,并将它存放在buf指向的结构中;IPC_SET:改变消息队列的状态,把buf所指的msqid_ds结构中的uid、gid、mode复制到消息队列的msqid_ds结构内。(内核为每个消息队列维护着一个结构,结构名为msqid_ds,这里就不讲啦,里面存放着消息队列的大小,pid,存放时间等一些参数)

    buf就是结构体msqid_ds

    **返回值:**成功返回0;错误返回-1

    **例如:**msgctl(id,IPC_RMID,NULL);删除id号的消息队列

    下面为一个简单的程序,一个service和一个client,service往消息队列里写数据,client从消息队列里读数据,当service输入QUIT时删除消息队列,并且俩程序都退出。

    1.service.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<sys/msg.h>
    #include<sys/ipc.h>
    struct mymesg{
    	long int mtype;
    	char mtext[512];
    };
    int main()
    {
    	int id = 0;
    	struct mymesg ckxmsg;
    	key_t key = ftok("/tmp",66);
    	id = msgget(key,IPC_CREAT | 0666);
    	if(id == -1)
    	{
    		printf("create msg error \n");
    		return 0;
    	}
    	while(1)
    	{
    		char msg[512];
    		memset(msg,0,sizeof(msg));
    		ckxmsg.mtype = 1;
    		printf("input message:");
    		fgets(msg,sizeof(msg),stdin);
    		strcpy(ckxmsg.mtext,msg);
     
    		if(msgsnd(id,(void *)&ckxmsg,512,0) < 0)
    		{
    			printf("send msg error \n");
    			return 0;
    		}
     
    		if(strncmp(msg,"QUIT",4) == 0)
    			break;
    	}
    	if(msgctl(id,IPC_RMID,NULL) < 0)
    	{
    		printf("del msg error \n");
    		return 0;
    	}
    	return 0;
    }
    

    2.client.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<sys/msg.h>
    #include<sys/ipc.h>
    struct mymesg{
    	long int mtype;
    	char mtext[512];
    };
    int main()
    {
    	int id = 0;
    	struct mymesg ckxmsg;
    	key_t key = ftok("/tmp",66);
    	id = msgget(key,0666|IPC_CREAT);
    	if(id == -1)
    	{
    		printf("open msg error \n");
    		return 0;
    	}
    	while(1)
    	{
    		if(msgrcv(id,(void *)&ckxmsg,512,1,0) < 0)
    		{
    			printf("receive msg error \n");
    			return 0;
    		}
    		printf("data:%s\n",ckxmsg.mtext);
    		if(strncmp(ckxmsg.mtext,"QUIT",4) ==0)
    			break;
    	}
    	return 0;
    }
    

    运行结果

    service
    在这里插入图片描述
    client
    在这里插入图片描述

    展开全文
  • linux 消息队列的限制

    千次阅读 2021-05-18 16:50:54
    消息队列的系统限制作者:冯老师,华清远见嵌入式学院讲师。消息队列是System V的IPC对象的一种,用于进程间通信,会受到系统的限制,本文主要描述了三个限制。第一:议个消息的最大长度;第二:消息队列的最大容量;...
  • linux 消息队列编程 linux 消息队列导读:就爱阅读网友为您分享以下“linux 消息队列”的资讯,希望对您有所帮助,感谢您对92的支持!消息队列 :是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源...
  • linux 消息队列API

    2022-04-28 08:00:34
    一. 什么是linux消息队列消息队列是提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有 一个类型,接收进程可以独立的接收含有不同类型的数据结构。我们可以通过发送消息来避免...
  • 一、概念消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;有读权限的进程则可以读走消息。读走就没有了。消息...
  • linux 消息队列 参数

    千次阅读 2021-05-13 10:52:45
    消息队列一、函数mq_open头文件mqueue.h;原型mqd_t mq_open(const char *name, int oflag, .../*mode_t mode,struct mq_attr* attr*/);函数功能创建消息队列;参数name:消息队列的名字,根据消息队列的规则,为了...
  • linux消息队列

    2020-07-29 14:40:55
    文章主要讲解有关linux消息队列的问题,感性趣的朋友可以参考下。
  • MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是...  消息队列与 FIFO 很相似,都是一个队列结构,都可以有多个进程往队列里面写信息,多个进程从队列中读取信息。
  • 本人初学ARM板开发,今天学习linux下的消息队列函数例子程序下载:1.key_tftok(char*pathname,charproj)返回文件名对应的键值(把消息队列当作文件处理)头文件:#include#includepathname:文件名proj:项目名(不为0...
  • linux消息队列总结

    2021-05-15 16:06:57
    1.消息队列简介实现linux进程通信的方式有5种:--信号(Singal)--管道(Pipe)--消息队列(Message)--信号量(Semaphore)每种进程通信方式实现方式和功能不一样,带来适用的场景也有所不同,消息队列是链表队列,它通过...
  • linux 消息队列

    2019-02-24 21:14:48
    消息队列:加强型的管道,他可以指定存放的数据类型,与取走的数据类型,方便不同进程取数据。 消息队列,共享内存,信号量:属于system V(5) 版本的进程通信,也叫ipc通信对象,除了system V进程间的通信外,我们...
  • linux消息队列的使用

    2021-05-16 11:51:15
    消息队列*消息队列是内核地址空间中的内部链表,通过内核在各个进程之间传递的内容。消息顺序发送到消息队列中,每个消息队列都有IPC标识符唯一地进行标识。msgbuf结构struct msgbuf{long mtype; //消息类型char ...
  • 【from:http://blog.csdn.net/cwj649956781/article/details/8804908】消息队列:1.每次msgrcv一个消息,1.那个消息会在内核中移除 2.每次msgrcv都只会给一个消息出来,不管你rcv用多大的buf来接收,都是可以的。...
  • 消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。 消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须...
  • 消息队列是进程间通信的一种方式 二、函数介绍 1、ftok函数生成键值 每一个消息队列都有一个对应的键值(key)相关联(共享内存、信号量也同样需要)。 头文件#include<sys/ipc.h> 函数原型 key_t ftok(const ...
  • Linux消息队列

    2021-10-05 19:07:21
    文章目录基本概念ftokmsgget消息格式msgsndmsgrcvmsgctl操作消息队列 基本概念   消息队列就是一个存储消息的链表,这些消息具有特定的格式,以及特定的优先级。   对消息队列有写权限的进程可以向其中添加新...
  • Linux消息队列讲解

    千次阅读 2018-04-10 21:11:42
    消息队列一、消息队列1. 消息队列消息的链表,存放在内存中,由内核维护2. 特点1)消息队列允许一个或多个进程向它写入或者读取消息,并且每条消息都有类型2)消息队列可以实现消息的随机查询,消息不一定要以...
  • linux POSIX消息队列详解&使用&demo 系统调用 mq_open() 打开一个消息队列, #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <...
  • 消息队列 消息队列亦称报文队列,也叫做信箱。是Linux的一种通信机制,这种通信机制传递的数据具有某种结构,而不是简单的字节流。 消息队列的本质其实是一个内核提供的链表,内核基于这个链表,实现了一个数据结构...
  • 一、什么是消息队列 消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。可以解决两个进程的读写速度不同(处理数据...
  • linux消息队列函数

    2021-05-15 00:51:01
    本人初学ARM板开发,今天学习linux下的消息队列函数例子程序下载:1.key_tftok(char*pathname,charproj)返回文件名对应的键值(把消息队列当作文件处理)头文件:#include#includepathname:文件名proj:项目名(不为0...
  • 消息队列linux下进程间通讯的常用方式之一,区别于共享内存,消息队列使用更加简单。但是,简单就没有坑么?在这里,想跟大家一起探讨下解锁消息队列的正确姿势,翠花,趴好~ 一、什么是消息队列 生产者先将...
  • 一、消息队列 消息队列用于同一台机器上的进程间...消息队列可以避免命名管道的同步和阻塞问题,但是每个数据块都有一个最大长度的限制。 1、msgget函数 #include <sys/types.h> #include <sys/ipc.h&g.
  • 进程用户空间是相互独立的,一般而言是不能相互访问的。...Linux系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。 key_t ftok( char * fname, int i
  • Linux消息队列编程(简单应用)

    万次阅读 多人点赞 2018-08-15 23:35:51
    消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。可以解决两个进程的读写速度不同(处理数据速度不同),系统耦合...
  • 消息队列消息的链表,存放在内核中并有消息队列标示符标示。msgget用于创建一个新队列或打开一个现存的队列。msgsnd将新消息加入到消息队列中;每个消息包括一个long型的type;和消息缓存;msgrcv用于从队列中取出...

空空如也

空空如也

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

linux 消息队列阻塞