【问题标题】:Create thread safe global store in C在 C 中创建线程安全的全局存储
【发布时间】:2019-03-11 09:52:35
【问题描述】:

我正在编写一个在 FreeRTOS 上运行的应用程序,其中我有不同的线程,它们都必须访问(读取和写入)相同的数据结构。 所以我想我可以实现一个全局数据存储,将所有数据保存在一些分组结构中。我也考虑过使用 SQLite 之类的东西,但我认为这对我的应用程序来说太过分了。

不过还是有一些悬而未决的问题

  1. 为了保证线程安全,我假设我需要为我的读写访问添加一个信号量,但是...
  2. 如果线程只需要更新结构的某些元素,我需要将一个指向该结构的指针交给它,但是一旦我开始使用指针引用,我就不能再用信号量来保护我的访问了。那么如何在不违反线程安全的情况下允许线程修改单个结构元素呢?
  3. 有没有比我计划使用的更好的方法来获得类似global store 的东西?谷歌没有给出太多提示。

【问题讨论】:

  • 信号量有什么问题?它在 FreeRTOS 中受支持。结构的数量是多少?
  • 我将其分为 6 个结构(有些较大有些较小)。我对信号量的问题(也许我错了)是,我将如何通过受信号量保护的指针引用修改数据?在修改结构之前从线程向lock()unlock() 添加一个函数?原因如果我按值修改数据,我会向存储中添加一个函数,如 void version_info_to_store(version_info data),然后将信号量锁定在此函数中。
  • 信号量的保护是组织问题。您不会直接保护结构不被访问,而是使用信号量作为标志“结构当前正在使用”。该标志不是简单的变量而是信号量,以确保任务切换不会在ifflag = 1 之间命中:if ( flag == 0 ) { flag = 1; modify_structure; flag = 0; }。您必须保证对结构的每次访问都受到同一个信号量的保护——这就是“组织”。 (注意:这只是一个解决方案,可能不是最好的。)
  • 所以修改任务是在修改存储之前请求访问结构?这就是我在商店本身中实现的lock()unlock() 函数的意思。
  • 是的,我认为它是相似的。不确定一个全局信号量(锁定/解锁)是否适用于所有结构,或者为每个结构提供单独的保护是否会更好。

标签: c store freertos


【解决方案1】:

让我与您分享处理此类场景的最常见的 C 方式。

为了避免暴露大量全局数据,请使用opaque pointers 并有一个将不透明指针作为参数的 API 列表。通过这种方式,您可以拥有一组干净的 API 来访问您的所有结构,而将实现细节留在 .c 文件中。使用不透明指针的好处是没有人知道如何处理指向数据的类型,除了将不透明指针作为参数的API。这为您的结构提供了保护和封装,因此您可以使用您提供的 API 访问或更改它们。

在由不透明指针标识的每个结构定义中,都有一个mutexFreeRTOS 已根据信号量实现互斥)以线程安全的方式访问结构成员。创建互斥锁时必须使用xSemaphoreCreateMutex。当您想要访问可能被多个任务访问的成员数据时,在所有 API 中使用 xSemaphoreGivexSemaphoreTake

【讨论】:

  • 如果我理解正确,这意味着如果我有一个包含 10 个不同值的结构,我希望能够单独修改这些值,那么我需要添加一个带有 getter 和 setter 的 API这 10 个值中的每一个?
  • @Humpawumpa 好吧,这取决于。如果您想单独访问它们,则需要 10 个 api。否则,您可以使用 1 个 api 以原子方式检索或访问整个 record。我假设您会将record 设置为由opaque pointer 标识的主结构内的子结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 2014-09-16
相关资源
最近更新 更多