c - 这个策略是为了避免 C 中的全局变量,对吗?

标签 c embedded global-variables encapsulation

<分区>

在我的(个人)嵌入式项目中,全局变量堆积如山。我需要这些变量可以从 ISR(中断服务例程)和/或菜单系统(以便用户可以修改它们)访问,但同时我想避免使用太多全局变量。

因为它们可以按模块分组,我想我可以将它们封装在它们自己的 .c 文件中,声明为 staticstatic volatile ,并暴露给外部world 一些函数来处理它们。

类似的东西:

在module1.c

#include module1.h

static volatile int module1_variable;

int getModule1Var(void){
    return module1_variable;
}

void setModule1Var(int i){
    //some code to disable interrupts for atomic operations
    module1_variable = i;
    //some other code to re-enable interrupts
    return;
}

module1.h 将包含函数原型(prototype)、结构和使模块正常工作的所有其他元素,当然静态变量定义除外

在 main.c 中

#include module1.h

void main(){
    //setting the variable value, could be done from a menu 
    setModule1Var(15);
    //remaining application code
}

void generic_ISR(){
    //trivial usage example
    doSomething(getModule1Var());
    return;
}

这个方案自然会扩展到其他模块。

现在我的问题是:
这是一个好方法吗?简单地拥有一堆全局变量是一样的吗?有什么主要缺点吗?

我还认为我可以使用某种混合方式,比如仍然让全局变量允许 ISR 直接操作(因为来自 ISR 的函数调用有时不受欢迎)和其他所有情况下的函数。这样会更好吗?

最佳答案

里面有几个问题:

is this a good approach?

是的。将 ISR 放置在与其共享的访问函数和数据相同的模块中,将其视为访问函数本身,允许它直接读取数据而无需访问包装器开销。


Is it better/worse/equal to simply have a bunch of globals?

更糟。对于全局,您打算在哪里放置访问互斥体、数据验证或断点?它增加了模块耦合,并且应该始终将其最小化。


Any major drawbacks?

不是真的。有一个函数调用开销,这在 ISR 中可能很关键;但如果这是一个问题,您就不会在 ISR 中调用 printf()!您可以应用我之前关于将 ISR 放置在数据模块中的建议或通过内联代码来减轻任何可能的性能损失 - 但您的编译器可以自由地忽略它,并且如果启用调试可能会这样做,也可能内联无论是否启用优化。一些编译器有一个不允许编译器忽略的“强制”内联扩展;但它不便携。

一个显着的好处是,如果变量是非原子变量,则您需要一些访问保护机制来确保一致的访问 - 而通过访问函数可以最轻松、最安全地执行此操作。在这种情况下,您可能有 get/set 函数来禁用和重新启用访问周围的中断,例如,或使用自旋锁(适用于 ISR 写入和正常上下文读取的位置 - 而不是相反的方式在这里 - 不要无限期地锁定 ISR!)。


I also thought I could use some sort of mix like still having the global variables to allow direct manipulation by the ISR (since function calls from the ISR are sometimes frown upon) and the functions in every other case. Would this be better?

不是真的 - 请参阅我上面关于函数调用开销和 ISR 与数据的放置的观点。在 ISR 中调用函数的问题很少是时间开销问题,而是函数的实现者可能没有将其设计为从 ISR 中安全有效地调用它,并且它可能使用过多的堆栈、不确定的执行时间,忙等待或不可重入或线程安全。例如,调用第三方或标准库函数可能是不明智的;调用您为此目的专门编写和设计的函数并符合您的特定约束不一定是问题。


关于为什么全局变量不是一个好主意以及避免它们的适当方法,您需要了解的所有信息都可以在 Jack Ganssle 的文章 "A Pox on Globals" 中找到。 - 这也是一本有趣的读物。

关于c - 这个策略是为了避免 C 中的全局变量,对吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43496618/

相关文章:

c - 如何标记 shell 输入?

c - 我如何知道输入是否是字母?我只能接受姓名中的字母和中间首字母的点

hadoop - 在reducer中设置并读取驱动程序的Hadoop变量

c++ - C 函数调用 C++ 成员函数 - C 代码是用 C 编译器编译的

c - 从 C 中的文本文件中读取和解析文本

c++ - 类中的静态变量和内存分配及其使用

windows - 即使 Windows 在缓存中有条目(ARP 表),也会发送 ARP 请求

qt - 什么是 Qt 裸机?

PHP:在函数内与 global 关键字一起使用时,全局变量将无法按预期工作

javascript - 将值附加到稍后调用的全局变量名称