我正在用C开发一个相当复杂的微 Controller 应用程序,我对如何在不同任务/线程之间“链接”我的共享数据而不耦合它们有一些疑问。
到目前为止,我一直使用时间切片调度程序来运行我的应用程序,因此不需要数据保护。但我想让应用程序正确,并且我想让它为以后的多线程操作系统做好准备。
我试图通过使用与我正在使用的实际系统完全不同的系统来简化我的问题。我无法添加图片,因为我是新用户,但我会尝试解释一下:
我们有 4 个任务/线程:3 个输入线程通过硬件抽象层 (HAL) 从不同的传感器读取一些传感器数据。收集到的传感器数据存储在任务域内(即:它们不会是全局的!!)。 现在我们还有 1 个输出任务,我们称之为“Regulator”。调节器必须使用(读取)从所有 3 个传感器收集的传感器数据才能生成正确的输出。
问题:Regulator 如何在不与其他任务耦合的情况下读取存储在不同输入任务中的收集数据?
监管机构必须仅通过引用了解输入任务及其数据(即:无#includes,无耦合)。
到目前为止,调节器已经有一个指向每个所需传感器数据的指针,并且该指针是在初始化时设置的。由于数据保护,这在多线程应用程序中不起作用。
我可以为每个传感器值创建一些使用信号量的 getSensorValue() 函数,然后使用函数指针将它们链接到调节器。但这会占用很多内存!有没有更优雅的方法来做到这一点?我只是在寻找输入。
我希望这一切都是可以理解的:)
最佳答案
根据您在问题和评论中的描述,您似乎最担心传感器和调节器之间的接口(interface)内存不足,实现细节最少,并且不知道每个传感器实现的明确细节。
由于您使用的是 C,并且没有一些 C++ 类功能,这些功能可以通过继承使封装变得更容易,所以我建议您从每个传感器线程创建一个公共(public)数据包,将其传递给调节器,而不是传递一个函数指针。形式的结构
struct SensorDataWrap {
DataType *data;
LockType *lock;
... other attributes such as newData or sensorName ...
};
允许您将数据传递给监管机构,您可以在读取之前锁定数据。同样,传感器在写入之前需要锁定。如果您将 data 更改为双指针 DataType **data
您可以使写入命令只需要锁定交换底层指针所需的时间。然后,调节器只需要每个线程的单个 SensorDataWrap 结构来处理该线程的信息,而不管传感器实现细节如何。
LockType 可以是信号量,或者任何支持单次访问获取的更高级别的锁定对象。任何此类锁的内存占用应该只有几个字节。此外,您不会在此处复制数据,因此相对于传感器读数,您不应该对内存大小产生任何倍增效应。您使用的硬件应该有足够的空间来保存来自您所描述的传感器的数据的单个副本,以及足够的闪存空间来容纳信号量或锁定对象。
通信的实现细节现在仅限于锁定、执行操作、解锁,并且不需要复杂的函数指针或 SensorN 特定 header 。它应该接近任何线程共享数据程序所需的最小逻辑。该程序还应该可以转移到其他微 Controller ,而无需进行重大更改 - 通信实际上仅受线程和锁的存在/不存在的限制。
另一种选择是传递三重缓冲区对象并进行缓冲区翻转以避免信号量和锁定。这种方法需要创建原子整数/ bool 支持(如果您有信号量,您很可能已经由编译器公开了)。使用三重缓冲区实现并发的指南可以在 this blog 上找到。 。这种方法将使用更多的事件内存,但是是避免大多数并发问题的一种非常巧妙的方法。
关于c - 如何在任务/线程之间共享数据而不耦合它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15793860/