在嵌入式 RTOS 任务之间传递消息的好方法(但可以优雅地处理消息超时)
我正在使用嵌入式 RTOS (CMX),但我认为这适用于任何嵌入式 RTOS。我想在不同任务之间传递消息。问题在于,一项任务有时会在很长一段时间内(几秒钟)“锁定”所有其他任务。
由于我不再等待大约 100 毫秒后消息被 ACK,如果我在这段时间发送邮箱消息,发送消息的任务不再等待它回复,但接收任务将得到并尝试采取行动。问题是接收任务有一个指向消息的指针,但由于发送任务已经转移,指针不再指向消息,这可能会导致巨大的问题。
一旦消息进入队列,我就无法删除它们。我怎样才能优雅地处理这个错误?
I'm working with an embedded RTOS (CMX), but I think this applies to any embedded RTOS. I want to pass messages between various tasks. The problem is that one task sometimes 'locks' every other task out for a long period of time (several seconds).
Since I no longer wait for the message to be ACK'ed after ~100 ms or so, if I send a mailbox message during this time, the task that sent the message is no longer waiting for it reply, but the receiving task will get the message and try to act on it. The problem is that the receiving task has a pointer to the message, but since the sending task has moved on, the pointer is no longer pointing to the message which can cause huge problems.
I have no method of removing messages once they are in the queue. How can I handle this error gracefully?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题实际上涵盖了几个不同的问题/点。
首先,我想知道为什么一个任务有时会占用 CPU 几秒钟。一般来说,这表明存在设计问题。但我不了解你的系统,可能有一个合理的解释,所以我不会陷入那个兔子洞。
因此,根据您的描述,您正在排队指向消息的指针,而不是消息的副本。这本身并没有什么错。但您可能会遇到您所描述的问题。
这个问题至少有两种解决方案。在不了解更多信息的情况下,我无法说出其中哪一个更好。
第一种方法是传递消息的副本,而不是指向它的指针。例如,VxWorks 消息队列(显然不是 CMX 队列)让您将消息的副本排入队列。我不知道CMX是否支持这样的模型,也不知道你是否有带宽/内存来支持这样的方式。一般来说,我会尽可能避免这种方法,但有时它也有其用处。
在这种情况下,我会尽可能使用第二种方法,即让发送者分配一个消息缓冲区(通常来自我自己的消息/缓冲区池,通常是固定大小内存块的链表 - 但这是一种实现详细信息 - 请参阅 “内存池”的描述用于说明我正在谈论的内容)。不管怎样——分配之后,发送者填写消息数据,将指向消息的指针排入队列,并释放内存块(即消息)的控制(所有权)。 接收者现在负责在读取消息后释放/返回内存。
这一问题还可能引发其他问题,例如,如果发送者将消息“广播”给多个接收者怎么办?接收器如何协调/通信,以便只有最后一个读取器释放内存(垃圾收集)?但希望根据您的要求,第二个解决方案适合您。
This question actually covers several different issues / points.
First of all, I'm wondering why one task hogs the CPU for seconds at a time sometimes. Generally this is an indication of a design problem. But I don't know your system, and it could be that there is a reasonable explanation, so I won't go down that rabbit hole.
So from your description, you are enqueueing pointers to messages, not copies of messages. Nothing inherently wrong with that. But you can encounter exactly the problem you describe.
There are at least 2 solutions to this problem. Without knowing more, I cannot say which of these might be better.
The first approach would be to pass a copy of the message, instead of a pointer to it. For example, VxWorks msg queues (not CMX queues obviously) have you enqueue a copy of the message. I don't know if CMX supports such a model, and I don't know if you have the bandwidth / memory to support such an approach. Generally I avoid this approach when I can, but it has its place sometimes.
The second approach, which I use whenever I can in such a situation, is to have the sender allocate a message buffer (usually from my own msg/buffer pools, usually a linked-list of fixed size memory blocks - but that is an implementation detail - see this description of "memory pools" for an illustration of what I'm talking about). Anyway -- after the allocation, the sender fills in the message data, enqueues a pointer to the message, and releases control (ownership) of the memory block (i.e., the message). The receiver is now responsible for freeing/returning the memory after reading the message.
There are other issues that could be raised in this question, for example what if the sender "broadcasts" the msg to more than one receiver? How do the receivers coordinate/communicate so that only the last reader frees the memory (garbage collection)? But hopefully from what you asked, the 2nd solution will work for you.