我正在研究一种使用网守任务来访问共享资源的设计。我现在拥有的基本设计是看门人任务从中接收的单个队列以及将请求放入其中的多个任务。
这是一个内存有限的系统,我使用的是 FreeRTOS(Cortex M3 端口)。
问题如下:异步处理这些请求相当简单。请求任务将其请求排队并继续其业务、轮询、处理或等待其他事件。为了同步处理这些请求,我需要一种机制来阻止请求任务,这样一旦请求被处理,网守就可以唤醒调用该请求的任务。
我能想到的最简单的设计是在每个请求中包含一个信号量,但考虑到内存限制和 FreeRTOS 中相当大的信号量,这是不切实际的。
我想出的是使用任务挂起和任务恢复功能手动阻止任务,将句柄传递给网守,它可以在请求完成时恢复任务。但是,暂停/恢复存在一些问题,我真的很想避免它们。无论任务被其他调用挂起多少次,一个恢复调用都会唤醒一个任务,这可能会产生不良行为。
一些简单的伪 C 来演示挂起/恢复方法。
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
task_suspend(this_task);
}
void gatekeeper_request_complete_callback(request)
{
task_resume(request->task);
}
我计划在此期间使用的一种解决方法是使用异步调用并在每个请求任务中完全实现阻塞。当操作完成时,网守将执行提供的回调,然后可以发布到任务的主队列或特定的信号量,或任何需要的东西。对请求进行阻塞调用本质上是一种便利功能,因此每个请求任务都不需要实现这一点。
伪 C 来演示特定于任务的阻塞,但这需要在每个任务中实现。
void requesting_task(void)
{
while(1)
{
gatekeeper_async_request(callback);
pend_on_sempahore(sem);
}
}
void callback(request)
{
post_to_semaphore(sem);
}
也许最好的解决方案就是不在网关守卫和 API 中实现阻塞,并强制每个任务处理它。不过,这会增加每个任务流程的复杂性,我希望我可以避免它。在大多数情况下,所有调用都希望阻塞,直到操作完成。
是否有一些我遗漏的结构,或者只是我可以用谷歌搜索的这类问题的更好术语?我在搜索中没有遇到过这样的事情。
附加说明- 看门人任务的两个原因:
需要大的堆栈空间。与其将这个要求添加到每个任务中,网关守卫可以拥有一个包含所有所需内存的堆栈。
CPU 中的资源并不总是可访问的。它不仅同步 CPU 中的任务,还同步 CPU 外的任务。