μC/OS-II---消息队列管理1(os_q.c)

目录

  • 消息队列的主要优点
  • 消息队列和消息邮箱
  • 消息队列相关操作
    • 消息队列创建
    • 消息队列删除
    • 在消息队列等待消息

在这里插入图片描述

消息队列的主要优点

  • 消息队列的主要优点是解耦和异步通信。发送者和接收者之间不需要直接建立连接,它们只需要知道消息队列的名称或标识符即可。发送者将消息发送到队列中后,可以继续执行其他任务,而不需要等待接收者处理消息。接收者可以在合适的时候从队列中获取消息进行处理,这样可以实现异步通信,提高系统的并发性和响应性。
  • 通常会在消息队列中引入消息标识符或者消息类型。发送者在发送消息时,会附带一个标识符或类型,接收者在接收消息时,会根据标识符或类型来判断是否是自己需要处理的消息。这样可以确保每个进程只处理属于自己的消息,避免了拿错信息的问题。
  • 此外,还可以使用互斥锁或其他同步机制来保证在读取和写入消息队列时的原子性操作,避免多个进程同时对消息队列进行读写操作而导致的竞争条件。

消息队列和消息邮箱

  • 消息队列是一个独立的数据结构,多个进程可以共享同一个消息队列,而消息邮箱是与进程关联的,每个进程都有自己的邮箱。此外,消息队列通常是先进先出(FIFO)的,而消息邮箱可以根据实现方式不同具有不同的特性,比如可以是先进先出或者按优先级处理消息。
  • Task也可以设计有“私有”消息队列模式。
  • 总的来说,消息队列更适合实现多个进程之间的解耦和异步通信,而消息邮箱更适合实现单个进程内的消息传递。

消息队列相关操作

消息队列创建

OS_EVENT  *OSQCreate (void    **start,INT16U    size)
{OS_EVENT  *pevent;OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE){OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}#endifif (OSIntNesting > 0u)                       /* See if called from ISR ...                         */{return ((OS_EVENT *)0);                  /* ... can't CREATE from an ISR                       */}OS_ENTER_CRITICAL();pevent = OSEventFreeList;                    /* Get next free event control block                  */if (OSEventFreeList != (OS_EVENT *)0)        /* See if pool of free ECB pool was empty             */{OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;}OS_EXIT_CRITICAL();if (pevent != (OS_EVENT *)0)                 /* See if we have an event control block              */{OS_ENTER_CRITICAL();pq = OSQFreeList;                        /* Get a free queue control block                     */if (pq != (OS_Q *)0)                     /* Were we able to get a queue control block ?        */{OSQFreeList            = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/OS_EXIT_CRITICAL();pq->OSQStart           = start;               /*      Initialize the queue                 */pq->OSQEnd             = &start[size];pq->OSQIn              = start;pq->OSQOut             = start;pq->OSQSize            = size;pq->OSQEntries         = 0u;pevent->OSEventType    = OS_EVENT_TYPE_Q;pevent->OSEventCnt     = 0u;pevent->OSEventPtr     = pq;
#if OS_EVENT_NAME_EN > 0upevent->OSEventName    = (INT8U *) (void *)"?";
#endifOS_EventWaitListInit (pevent);                /*      Initialize the wait list             */}else{pevent->OSEventPtr = (void *)OSEventFreeList; /* No,  Return event control block on error  */OSEventFreeList    = pevent;OS_EXIT_CRITICAL();pevent = (OS_EVENT *)0;}}return (pevent);
}

消息队列删除

#if OS_Q_DEL_EN > 0u
OS_EVENT  *OSQDel (OS_EVENT  *pevent,INT8U      opt,INT8U     *perr)
{BOOLEAN    tasks_waiting;OS_EVENT  *pevent_return;OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0){OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}#endif
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0)                           /* Validate 'pevent'                        */{*perr = OS_ERR_PEVENT_NULL;return (pevent);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q)            /* Validate event block type                */{*perr = OS_ERR_EVENT_TYPE;return (pevent);}if (OSIntNesting > 0u)                                 /* See if called from ISR ...               */{*perr = OS_ERR_DEL_ISR;                            /* ... can't DELETE from an ISR             */return (pevent);}OS_ENTER_CRITICAL();if (pevent->OSEventGrp != 0u)                          /* See if any tasks waiting on queue        */{tasks_waiting = OS_TRUE;                           /* Yes                                      */}else{tasks_waiting = OS_FALSE;                          /* No                                       */}switch (opt){case OS_DEL_NO_PEND:                               /* Delete queue only if no task waiting     */if (tasks_waiting == OS_FALSE){
#if OS_EVENT_NAME_EN > 0upevent->OSEventName    = (INT8U *) (void *)"?";
#endifpq                     = (OS_Q *)pevent->OSEventPtr;  /* Return OS_Q to free list     */pq->OSQPtr             = OSQFreeList;OSQFreeList            = pq;pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr     = OSEventFreeList; /* Return Event Control Block to free list  */pevent->OSEventCnt     = 0u;OSEventFreeList        = pevent;          /* Get next free event control block        */OS_EXIT_CRITICAL();*perr                  = OS_ERR_NONE;pevent_return          = (OS_EVENT *)0;   /* Queue has been deleted                   */}else{OS_EXIT_CRITICAL();*perr                  = OS_ERR_TASK_WAITING;pevent_return          = pevent;}break;case OS_DEL_ALWAYS:                                /* Always delete the queue                  */while (pevent->OSEventGrp != 0u)              /* Ready ALL tasks waiting for queue        */{(void)OS_EventTaskRdy (pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);}#if OS_EVENT_NAME_EN > 0upevent->OSEventName    = (INT8U *) (void *)"?";
#endifpq                     = (OS_Q *)pevent->OSEventPtr;   /* Return OS_Q to free list        */pq->OSQPtr             = OSQFreeList;OSQFreeList            = pq;pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr     = OSEventFreeList;     /* Return Event Control Block to free list  */pevent->OSEventCnt     = 0u;OSEventFreeList        = pevent;              /* Get next free event control block        */OS_EXIT_CRITICAL();if (tasks_waiting == OS_TRUE)                 /* Reschedule only if task(s) were waiting  */{OS_Sched();                               /* Find highest priority task ready to run  */}*perr                  = OS_ERR_NONE;pevent_return          = (OS_EVENT *)0;       /* Queue has been deleted                   */break;default:OS_EXIT_CRITICAL();*perr                  = OS_ERR_INVALID_OPT;pevent_return          = pevent;break;}return (pevent_return);
}
#endif

在消息队列等待消息

void  *OSQPend (OS_EVENT  *pevent,INT32U     timeout,INT8U     *perr)
{void      *pmsg;OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0){OS_SAFETY_CRITICAL_EXCEPTION();return ((void *)0);}#endif
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0)                 /* Validate 'pevent'                                  */{*perr = OS_ERR_PEVENT_NULL;return ((void *)0);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_Q)  /* Validate event block type                          */{*perr = OS_ERR_EVENT_TYPE;return ((void *)0);}if (OSIntNesting > 0u)                       /* See if called from ISR ...                         */{*perr = OS_ERR_PEND_ISR;                 /* ... can't PEND from an ISR                         */return ((void *)0);}if (OSLockNesting > 0u)                      /* See if called with scheduler locked ...            */{*perr = OS_ERR_PEND_LOCKED;              /* ... can't PEND when locked                         */return ((void *)0);}OS_ENTER_CRITICAL();pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */if (pq->OSQEntries > 0u)                     /* See if any messages in the queue                   */{pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */pq->OSQEntries--;                        /* Update the number of entries in the queue          */if (pq->OSQOut == pq->OSQEnd)            /* Wrap OUT pointer if we are at the end of the queue */{pq->OSQOut = pq->OSQStart;}OS_EXIT_CRITICAL();*perr = OS_ERR_NONE;return (pmsg);                           /* Return message received                            */}OSTCBCur->OSTCBStat     |= OS_STAT_Q;        /* Task will have to pend for a message to be posted  */OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly       = timeout;          /* Load timeout into TCB                              */OS_EventTaskWait (pevent);                   /* Suspend task until event or timeout occurs         */OS_EXIT_CRITICAL();OS_Sched();                                  /* Find next highest priority task ready to run       */OS_ENTER_CRITICAL();switch (OSTCBCur->OSTCBStatPend)                  /* See if we timed-out or aborted                */{case OS_STAT_PEND_OK:                         /* Extract message from TCB (Put there by QPost) */pmsg =  OSTCBCur->OSTCBMsg;*perr =  OS_ERR_NONE;break;case OS_STAT_PEND_ABORT:pmsg = (void *)0;*perr =  OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */break;case OS_STAT_PEND_TO:default:OS_EventTaskRemove (OSTCBCur, pevent);pmsg = (void *)0;*perr =  OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */break;}OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endifOSTCBCur->OSTCBMsg           = (void      *)0;    /* Clear  received message                       */OS_EXIT_CRITICAL();return (pmsg);                                    /* Return received message                       */
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/180505.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubectl get nodes报错:The connection to the server localhost:8080

报错描述kubectl get nodes命令无法执行 在K8S-master初始化后,worker-node节点加入K8S集群后 kubeadm join 192.168.31.150:6443 --token 2n0t62.gvuu8x3zui9o8xnc \--discovery-token-ca-cert-hash sha256:d294c082cc7e0d5f620fb10e527a8a7cb4cb6ccd8dc45ffaf2c…

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录 一、登录优化-redis 1、SpringBoot集成redis 1.1 pom 1.2 yml 1.3 测试程序(非必须) 1.4 启动redis,执行测试程序 2、令牌主动失效(代码优化) 2.1 UserController设置token到redis 2.2 登录拦截器Log…

Perl的LWP::UserAgent库爬虫程序怎么写

Perl的LWP::UserAgent库是一个用于发送HTTP请求的Perl模块。它可以用于编写Web爬虫、测试Web应用程序、自动化Web操作等。以下是一个简单的使用LWP::UserAgent库发送HTTP GET请求的Perl脚本的例子: #!/usr/bin/perluse strict; use warnings; use LWP::UserAgent;# …

Chrome 浏览器经常卡死问题解决

Chrome 浏览器经常卡死问题解决 chrome 任务管理器杀进程 mac 后台有很多 google chrome helper 线程并且内存占用较高 一直怀疑是插件的锅 其实并不是-0- 查看是哪个网页,哪个插件占用内存 chrome 更多工具 -> 任务管理器 切换到稳定版本的 chrome&#xff0c…

计算机网络之物理层

物理层 1. 物理层的基本概念 2.物理层下面的传输媒体 传输媒体可分为两类,一类是导引型传输媒体,另一类是非导引型传输媒体。 3.传输方式 3.1 串行传输和并行传输 串行传输:串行传输是指数据是一个比特依次发送的,因此在发送端…

舞台演出控制软件:QLab Pro

QLab Pro是一款功能强大的现场多媒体控制器软件,专为Mac用户设计。它提供了一个直观简洁的用户界面,使得用户能轻松管理和组织所有的媒体资源。QLab Pro支持导入各种音频和视频文件,并具备强大的音频、视频处理和灯光控制功能,可以…

每日一题:编写程序,使程序分别输出两个整数的加减乘除运算结果

文章目录 每日一题一、编写程序,使程序分别输出两个整数的加减乘除运算结果以下是一个使用 Java 编写的程序,可以输出两个整数的加减乘除运算结果:以下是一个简单的 Python 程序,可以计算两个整数的加减乘除运算结果: …

DevExpress WinForms HeatMap组件,一个高度可自定义热图控件!

通过DevExpress WinForms可以为Windows Forms桌面平台提供的高度可定制的热图UI组件,体验DevExpress的不同之处。 DevExpress WinForms有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程…

【Hadoop】MapReduce详解

🦄 个人主页——🎐开着拖拉机回家_大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁&#x1f…

Linux 系统编程,Binder 学习,文件访问相关的接口

文章目录 Linux 系统编程,Binder 学习,文件访问相关的接口1.概念2.linux文件结构3.文件描述符4.Linux文件系统的两类常用接口,linux系统内置库函数4.1 open4.2 close4.3 read4.4 write 5.标准I/O库函数5.1 fopen Linux 系统编程,B…

CCF ChinaSoft 2023 论坛巡礼|自动驾驶仿真测试论坛

2023年CCF中国软件大会(CCF ChinaSoft 2023)由CCF主办,CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办,将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

C语言:简单的用二维数组打印杨氏三角

杨辉三角&#xff0c;又称帕斯卡三角&#xff0c;是一个数学上的规律图形。它的构造规则如下&#xff1a; 每一行的两个端点数字是1。从第三行开始&#xff0c;每个数字是它上方两个数字的和。每一行数字左右对称。 #include<stdio.h> int main() {int arr[50][50];//定…