总结一下公司主机系统的任务通讯方式,任务的通讯方式用的是消息队列。

一、创建消息队列
创建消息队列的函数为OSQCreat(),其定义为:

OS_EVENT *OSQCreate (void **start, INT16U size)

以GSM任务和实时任务为例,创建消息队列。
1、首先创建消息队列变量指针定义

OS_EVENT * pRealTime_MsgQueue  = 0;
OS_EVENT * pGSM_MsgQueue  = 0;

2、给消息队列分配内存空间

#define  REALTIME_MSG_QUEUE_SIZE         (250)
#define  GSM_MSG_QUEUE_SIZE                   (250)
void * paReakTime_MsgQueueTbl[REALTIME_MSG_QUEUE_SIZE];
void * paGSM_MsgQueueTbl[GSM_MSG_QUEUE_SIZE];

3、创建消息队列

pRealTime_MsgQueue = OSQCreate(&paReakTime_MsgQueueTbl[0], REALTIME_MSG_QUEUE_SIZE);
pGSM_MsgQueue = OSQCreate(&paGSM_MsgQueueTbl[0], GSM_MSG_QUEUE_SIZE);

二、定义消息内存
为了消息有一个统一的规范且尽量减少内存的消耗,定义了一套标准的消息格式。这套格式有3种,定义名称为大消息、中消息和小消息,格式如下:

typedef struct _STRU_MEM_SMALL
{INT16U usMsgID;                             /* 消息ID */INT8U  ucMsgType;                         /* 消息类型,大中小,应用接收到消息后进行相应的解析 */INT8U  ucParam;                             /* 参数,可以携带额外的参数,默认未使用 */INT8U  ucData[16];
}STRU_MEM_SMALL,*pSTRU_MEM_SMALL;
typedef struct _STRU_MEM_MIDDLE
{INT16U usMsgID;                             /* 消息ID */INT8U  ucMsgType;                         /* 消息类型,大中小,应用接收到消息后进行相应的解析 */INT8U  ucParam;                             /* 参数,可以携带额外的参数,默认未使用 */INT8U  ucData[84];                            /* 消息内容 */
}STRU_MEM_MIDDLE, *pSTRU_MEM_MIDDLE;
typedef struct _STRU_MEM_BIG
{INT16U usMsgID;                             /* 消息ID */INT8U  ucMsgType;                         /* 消息类型,大中小,应用接收到消息后进行相应的解析 */
//  INT8U  ucParam;                              /* 参数,可以携带额外的参数,默认未使用 */INT16U usLen;                                 /* 消息实际内容的长度 */INT8U  ucData[2000];                         /* 消息内容 */
}STRU_MEM_BIG, *pSTRU_MEM_BIG;

1、定义消息指针

OS_MEM *g_pOS_MemSmall  = 0;
OS_MEM *g_pOS_MemMiddle = 0;
OS_MEM *g_pOS_MemBig    = 0;

2、定义消息内存空间

/* 单位内存块的大小定义(单位 字节) */
#define  OS_MEMSIGNAL_SIZE_SMALL        (20)         /*  */
#define  OS_MEMSIGNAL_SIZE_MIDDlE       (88)         /*  */
#define  OS_MEMSIGNAL_SIZE_BIG          (2006)  /*  *//* 各个内存池中,内存块的数量定义 */
#define  OS_MEMMAX_COUNT_SMALL          (100)    /*  */
#define  OS_MEMMAX_COUNT_MIDDLE         (10)         /*  */
#define  OS_MEMMAX_COUNT_BIG            (5)      /*  */

3、分配消息内存空间
首先定义消息指针,并初始化:

INT8U g_MemBuff_Small[OS_MEMSIGNAL_SIZE_SMALL    * OS_MEMMAX_COUNT_SMALL ] = {0};
INT8U g_MemBuff_Middle[OS_MEMSIGNAL_SIZE_MIDDlE * OS_MEMMAX_COUNT_MIDDLE] = {0};
INT8U g_MemBuff_Big   [OS_MEMSIGNAL_SIZE_BIG    * OS_MEMMAX_COUNT_BIG   ] = {0};

然后给消息指针分配内存空间,使用的是OSMemCreate()函数

g_pOS_MemSmall   = OSMemCreate((void * )g_MemBuff_Small ,OS_MEMMAX_COUNT_SMALL  ,OS_MEMSIGNAL_SIZE_SMALL    ,&ucError);
g_pOS_MemMiddle = OSMemCreate((void * )g_MemBuff_Middle ,OS_MEMMAX_COUNT_MIDDLE ,OS_MEMSIGNAL_SIZE_MIDDlE  ,&ucError);
g_pOS_MemBig    = OSMemCreate((void * )g_MemBuff_Big   ,OS_MEMMAX_COUNT_BIG    ,OS_MEMSIGNAL_SIZE_BIG      ,&ucError);

三、进程通讯
啰嗦了这么久,终于介绍到到进程间的通讯了。项目中每个任务都使用一个统一的格式,任务通常处于挂起的状态,只有消息队列非空的时候才会任务才会运行,格式如下:

void Task(OS_EVENT * MsgQueue,STRU_PARAM *param)
{void * pMsgVoid;INT8U ucMsgType;INT16U usMsgId;Init();     /* 各种初始化 */...........while(1){pMsgVoid = OSQPend(MsgQueue,20, &ucOSError);if(pMsgVoid){usMsgId   = GET_MSG_ID(pMsgVoid);ucMsgType = GET_MSG_TYPE(pMsgVoid);if(usMsgId){/* 处理消息 */}OS_FreeMem(ucMsgType,pMsgVoid);               /* 清空内存 */}}
}

这其中涉及到的函数定义如下:

#define GET_MSG_ID(pMsg)     (*((INT16U *)(pMsg)))       /* 因为大中小类型的消息头都相同,所以可以通过统一的方法获得消息ID */
#define GET_MSG_TYPE(pMsg)  (*(((INT8U *)(pMsg)) + 2)) /* 因为大中小类型的消息头都相同,所以可以通过统一的方法获得消息类型 */
#define GET_MSG_PARAM(pMsg) (*(((INT8U *)(pMsg)) + 3)) /* 因为大中小类型的消息头都相同,所以可以通过统一的方法获得消息类型 */

通过上面可以看到,任务处于等待消息状态,只有收到消息后才会执行判断。且在收到队列消息后强制转化成我们定义的消息类型,由消息类型得知,第一位为消息ID,第二位为消息类型,第三位之后的为消息内容。

介绍完接收消息,之后肯定要介绍发送消息了。之所以能把队列中的数据强制转换,得到想要的消息,正是由于有统一的发送格式。

发送消息队列使用的是OSQPost()函数,不过在队列发送前需要对数据进行封装。

INT8U SendMsg_Small(OS_EVENT * queue, STRU_MEM_SMALL * pSmallMsg)
{return SendMsg(queue,(void*)pSmallMsg);
}
INT8U SendMsg_Middle(OS_EVENT * queue, STRU_MEM_MIDDLE * pMiddleMsg)
{return SendMsg(queue,(void*)pMiddleMsg);
}
INT8U SendMsg_Big(OS_EVENT * queue, STRU_MEM_BIG * pBigMsg)
{return SendMsg(queue,(void*)pBigMsg);
}
INT8U SendMsg(OS_EVENT * queue, void * pMsg)
{INT8U res;INT8U ucError;INT8U type;INT32U size;INT8U *pVoid;if(queue!=0 && pMsg != 0){type = GET_MSG_TYPE(pMsg);      /* 通过强制转换,获取到消息类型 */size = OS_GetMemSize(type);pVoid = OS_AllocMem(type,&ucError);if(0 == pVoid)return 0xE1;if(ucError == OS_NO_ERR && size != 0){memcpy(pVoid,pMsg,size);ucError = OSQPost(queue, pVoid );if(ucError == OS_ERR_NONE){                                    /* 发送成功 */res = 0;}else{ucError = OS_FreeMem(type,pVoid);if(ucError == OS_ERR_NONE){res = 0xE4;                  /* 发送失败后,释放空间 */}else{res = 0xE5;                  /* 发送失败后,释放空间失败 */}}}else{res = 0xE2;                          /* 申请内存池错误 或者 消息类型/大小错误 */}}else{res = 0xE1;                              /* 参数错误 */}return res;
}

uCO/OS-ii 一种进程通讯总结相关推荐

  1. android中跨进程通讯的4种方式

    由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于andro ...

  2. Android 跨进程通讯的方式

    我已知Android 的跨进程通信方式有6种,分别为:访问他应用的Activity.接收其他应用的广播.访问其它应用的 开放数据.AIDL.Messenger和socket的跨进程通信. (1)访问他 ...

  3. Android进阶——Android跨进程通讯机制之Binder、IBinder、Parcel、AIDL

    前言 Binder机制是Android系统提供的跨进程通讯机制,这篇文章开始会从Linux相关的基础概念知识开始介绍,从基础概念知识中引出Binder机制,归纳Binder机制与Linux系统的跨进程 ...

  4. Android跨进程通讯机制之Binder、IBinder、Parcel、AIDL

    https://blog.csdn.net/qq_30379689/article/details/79451596 前言 Binder机制是Android系统提供的跨进程通讯机制,这篇文章开始会从L ...

  5. UART0串口编程(四):UART0串口编程之在UC/OS—II中遭遇的危机

    UART0串口编程之在UC/OS-II中遭遇的危机 一.潜在的危机 1.在uc/os操作系统中设计串口编程时,由于ISR和多个任务并发执行,情况比较复杂.尤其是接收状态为被动状态时,只能靠串行口中断来 ...

  6. electron 主进程与渲染进程通讯

    主进程和渲染器进程 Electron 有两种进程:主进程和渲染进程. 主进程通过创建 BrowserWindow 实例来创建 网页. 每一个 BrowserWindow 实例在其渲染过程中运行网页, ...

  7. 在 macOS 中如何使用 XPC 实现跨进程通讯?

    以防丢失,转载自: http://davidleee.com/2020/07/20/ipc-for-macOS/ 如侵权,联系删除 最近需要在 Electron 项目上引入一个比较吃性能的大头功能,因 ...

  8. 嵌入式实时操作系统μC/OS II(一)

    嵌入式实时操作系统μC/OS II 为什么要学习μC/OS-II ㈠.凡从事嵌入式系统开发工作的人,必须对嵌入式操作系统有足够的了解. ㈡.对于初学者,从μC/OS-II开始是个明智的选择. 1.μC ...

  9. php多线程模型,PHP进程模型、进程通讯方式、进程线程的区别分别有哪些?

    PHP进程模型是一个正在执行的程序,可以分配给处理器并由处理器执行的一个实体:PHP进程通讯方式有管道及有名管道,信号,共享内存等:PHP进程线程的区别有进程是资源的分配和调度的一个独立单元,而线程是 ...

最新文章

  1. 2022-2028年中国半导体用环氧塑封料(EMC)行业市场全景调查及投资前景分析报告
  2. append 降低数组位数_腿粗有理!研究发现腿部脂肪多,能大幅降低患高血压的风险!...
  3. PostgreSQL的那点事儿
  4. 设备管理系统html,蓝色的远程监控设备系统后台管理界面html模板
  5. cad无法加载arx文件_多年经验总结CAD技巧8
  6. Daily Scrum02 12.09
  7. 深度学习-Tensorflow2.2-Eager模式与自定义训练{4}-微分运算训练练习-16
  8. linux防火墙停用,关闭LINUX防火墙
  9. Combobox报错:row[opts.textField].toLowerCase is not a function。
  10. Nginx的配置实例(反向代理准备工作)
  11. mybatis是否接受运算符参数化
  12. android比较两个字符串,关于java:两个字符串的比较在android中不起作用
  13. 一张纸厚度是多少毫米_科学有意思 |一张纸对折,最多只能折9次?不信你试一试...
  14. 【数字信号】基于matlab CEEMD数字信号分解【含Matlab源码 1383】
  15. php 后端服务错误定义,【后端开发】php常见的错误类型有哪四种
  16. 使用ld的wrap选项替换已有库函数
  17. 企业直播活动策划方案怎么做
  18. r语言导出文件为xlxs_【软件】R语言数据导入与导出
  19. 简单谈谈编程语言(二)
  20. python查看虚拟环境列表_python虚拟环境virtualenv高级篇

热门文章

  1. Python 自动交替排班
  2. 阿里云面向企业效率的云上产品全解析:云桌面、云AP、云投屏
  3. 【无线网络技术专题(九)】全网最全!典型室内场景无线网络部署方案!
  4. VR线上虚拟展厅,为企业带来的优势:
  5. 【OpenCV-Python】14.OpenCV的边缘检测
  6. 学习Android开发是否有前途?
  7. 360公司运维面试题
  8. 锂电池升压到5V1A,FS2114升压IC设计布局
  9. 【Python 第23课】 list的介绍
  10. 9.9能买什么?80节北美外教AI课+158张单词卡+6张卡通贴纸+1张字母表+Leo单肩小书包........