2013-04-03 21 views
1

我正在开发一个相当复杂的微控制器应用程序C,我对如何将不同任务/线程之间的共享数据“链接”而不耦合它们存在一些疑问。如何在任务/线程之间共享数据而不耦合它们?

到现在为止,我已经使用了时间片调度程序来运行我的应用程序,因此不需要数据保护。但是我想让应用程序正确,我想在稍后为多线程操作系统做好准备。

我试图通过使用完全不同的系统,而不是我正在工作的实际系统来简化我的问题。我无法添加图片,因为我是新用户,但生病尝试并解释:

我们得到4个任务/线程:3个输入线程,通过硬件抽象层(HAL)从不同传感器读取一些传感器数据。 。收集的传感器数据存储在任务域(即:他们不会是全球性的!)。 现在我们还有1个输出任务,我们称之为“调节器”。调节器必须使用(读取)从所有3个传感器收集的传感器数据才能生成正确的输出。

问题:Regulator如何读取存储在不同输入任务中的采集数据而不与其他任务耦合?

调节器只能通过参考知道输入任务及其数据(即:不包含,不耦合)。

到目前为止,Regulator已经有了一个指向每个所需传感器数据的指针,并且该指针在初始化时设置。由于数据保护,这不会在多线程应用程序中工作。

我可以做一些getSensorValue()功能,它利用信号量,为每个传感器值,然后用函数指针将这些函数链接到调节器。但是这会占用很多内存!有没有更好的方法来做到这一点?我只是在寻找投入。

我希望这一切都是可以理解的:)

+0

你在运行什么硬件?微控制器系列对可以完成的工作产生很大的影响。例如在许多微控制器上没有虚拟内存。在其他控制器的“线程”中实际上并不是线程,而只是看门狗交换的堆栈指针。 – Pyrce

+0

目前我在PSoC5上运行,我计划进行端口/转换为STM32? – Jolle

+0

这些家族看起来有真正的线程/虚拟内存表。当你说数据保护会阻止应用程序读取线程特定的数据时,你的意思是说这些'线程'是作为进程而不是线程启动的吗?因为线程可以读取其他线程的内存,除非你用'__thread'等线程本地关键字来显式地限制内存。你认为什么内存很多,3个信号灯应该只占用几个字节的内存。或者由于传感器的读取速度,线程不能被延长时间阻塞? – Pyrce

回答

2

从您的问题描述了和评论,好像你最担心内存不足的以最小的实施细则,并没有传感器和监管者之间的接口是了解每个传感器实现的明确细节。

由于您在C中,并且没有一些C++类的特性可以通过继承来简化封装,所以我建议您从每个传递给调节器的传感器线程创建一个通用数据包,而不是传递一个函数指针。形式

struct SensorDataWrap { 
    DataType *data; 
    LockType *lock; 
    ... other attributes such as newData or sensorName ... 
}; 

的结构将允许您将数据传递到监管机构,在那里你可以阅读前锁定。同样,传感器在写入之前需要锁定。如果您将数据更改为双指针DataType **data,则可以使写命令只需锁定交换基础指针所需的时间。然后,调节器只需要每个线程的一个SensorDataWrap结构来处理该线程的信息,而不管传感器实现细节如何。

LockType可能是一个信号量,或者任何能够实现单一访问获取的更高级锁定对象。任何此类锁的内存占用空间应仅为几个字节。此外,您并不是在这里复制数据,因此相对于传感器读数,您不应该对内存大小产生任何乘法影响。您使用的硬件应具有足够的空间来容纳来自所描述的传感器的单个数据副本以及足够的闪存空间以容纳信号量或锁定对象。

通信的实现细节现在仅限于锁定,操作,解锁,不需要复杂的函数指针或SensorN特定的头文件包含。它应该接近任何线程共享数据程序所需的最小逻辑。该程序也应该可以转移到其他微控制器而没有重大改变 - 通信仅仅受到线程和锁定的存在/限制的限制。

另一种选择是传递三重缓冲区对象并做缓冲区翻转以避免信号量和锁定。这种方法需要创建原子整数/布尔支持(如果您有信号量,最有可能已由编译器公开)。可以在this blog上找到使用三重缓冲区并行的指南。这种方法将使用更多的活动内存,但它是避免大多数并发问题的一种非常流畅的方式。

+0

好的!这听起来(有点像)消息队列,我有这个想法,但结论(实际上没有任何好的论据),这是一个矫枉过正。虽然这不完全是你说的对吗?如果我明白这个权利,Regulator应该有一个SensorDataWrap的实例(应该为传感器和调节器btw声明typedef),并且SensorDataWrap里面有两个数据和某种保护机制。我喜欢这个主意!虽然我不太了解双指针部分。 – Jolle

+0

的确,我写出来的实现是一个简化的消息队列,监管者负责在数据被传感器覆盖之前读取数据。一个消息队列的实现也会起作用,而且不会矫枉过正。双指针是一个小调。单个指针版本要求传感器在将所有读数写入数据的同时保持锁定。一个双指针可以让他们写入一个新的“数据”对象,并且只有在他们改变指针以解决新读取时才锁定。这需要内存管理,所以它不是明显更好。 – Pyrce

+0

好吧,我认为这比消息队列更好,因为调节器是实时的,因此它不一定会像传感器产生的那样快地消耗数据。监管机构应该随时访问最新的数据。但非常感谢你,那只是我正在寻找的那种输入! – Jolle