嵌入式模块化设计中的数据共享优化方案
问题的提出
在嵌入式项目中,模块化每个功能有利于管理和理清开发思路,但是,当我们需要将模块联动起来的时候,需要一些必要的变量以实现两个模块之间的互相配合,最常见的方法是使用全局变量,但这样做使模块间耦合性[1]大大提高了。
有什么更好的方案吗
有的兄弟有的。只不过要牺牲一些效率(需要通过接口访问)。我们可以为共享变量建立一个专门的.c/.h文件,例如SharedData.c/.h
。
这个文件集中管理模块间的共享变量。这样做结构清晰,每个模块只依赖 SharedData.h
,而不是彼此依赖\
同时我们通过两种方法使需要访问变量的模块成功读取或修改变量:
- 结构体封装+指针传递
- 通过函数提供读取和修改的接口
结构体封装+指针传递
👍
- 共享变量较多时非常好用。
- 隐藏全局变量,外部模块无法直接访问共享数据而是通过指针,安全性高。
- 更好扩展。
- 方便,无需为每个变量都写函数接口以提供修改与读取。
- 访问速度快。
.h文件
1 |
|
.c文件
1 |
|
在其他模块中使用
1 |
|
⚠
不推荐将接收共享变量的指针的变量定义为全局变量。尽管这样会方便一些。指针可能被多个模块修改,导致指向无效地址(增加 bug 风险)。推荐在每个函数内部通过接口访问变量。如果一定要这样做,请一定避免空指针(记住初始化指针)
使用全局指针示例:
1 | static SharedData *data; // 仅限当前文件访问 |
通过函数提供读取和修改的接口
👍
- 灵活访问变量。你可以严格控制对数据的访问,如只读、避免非法值写入等;同时也可以自定义访问方法,如按位读取。非常的好用。
- 可扩展性强。
❌
- 代码冗长,调用花销稍大。
- 变量太多时需要为每个变量都写接口,太麻烦。所以才要和上面的方法联合起来使用,只为必要的变量编写接口,其余通过第一种方法访问。
.h文件
1 |
|
.c文件
1 |
|
在其他模块中使用
1 |
|
联合起来
将两种方式联合起来使用——大部分变量,我们使用指针接口访问即可;如果有些变量需要一些个性化要求,我们为这些变量编写定制的接口就好。
挖坑
降低耦合性的方法还有使用单例模式,以及RTOS中的消息/事件机制。后续研究。
代码耦合性(Coupling)是指模块或组件之间的依赖程度。如果代码耦合性很高,模块之间会紧密依赖,导致代码难以维护、扩展和测试。 ↩︎