【问题标题】:Are global variables as frowned upon in embeded systems programming (C)?嵌入式系统编程 (C) 中是否不赞成全局变量?
【发布时间】:2018-02-04 13:44:00
【问题描述】:

多年前我了解到,在应用程序世界中,全局变量是“不好的”或“不受欢迎的”,因此尝试避免使用它们并很少使用它们已成为一种习惯。

似乎在嵌入式世界中,当涉及到硬件中断时,它们几乎是不可避免的。还必须将它们设置为易失性,以便编译器在看到它们从未在运行的程序中被触及时不会优化它们。

这两种说法都是真的吗?在我描述的情况下,有没有办法避免这些变量而不会向后弯曲太远?

【问题讨论】:

  • Globals 不好是无稽之谈。只需要知道您在做什么并了解 .data 消耗(固定)和堆栈(动态)之间的权衡。特别是在资源有限的嵌入式环境中,并且在堆栈消耗方面存在问题,这很难确定全局变量在哪里容易。它们是在同一二进制文件中的函数/对象之间进行通信的一种但不是唯一的方式。语言的一部分,以及在函数/对象之间进行通信的最简单/最便宜(资源)的方式。
  • 你的标题问题是静态的,你的意思是全局的吗?
  • @old_timer,@Chris Stratton:你们都是对的。我想我的意思是全局变量。这对我来说是一个糟糕的选择
  • 现在已经指出解决问题 - 您可以对其进行编辑,这就是您在 SO 上响应 cmets 应该做的事情。全局变量是完全可以避免的,在嵌入式系统中应该避免尤其是。阅读:Jack Ganssle's A pox on globals。它准确地回答了你的问题。
  • @Lundin 的建议; “你可以使用放置在文件范围内的变量”是真实而重要的,但也需要应用最大内聚/最小耦合原则。例如,将所有代码放在一个文件中就达不到目的了。

标签: variables static coding-style embedded conventions


【解决方案1】:

似乎在嵌入式世界中,当 涉及到硬件中断。他们也必须是 变得易失,这样编译器就不会优化它们,如果它 看到它们在运行的程序中从未被触及。

这两种说法都是真的吗?有没有办法避免那些 我描述的情况下的变量没有向后弯曲太远?

这些说法都不正确。

首先,让我们澄清一下,全局变量是指具有外部链接的文件范围变量。这些变量可能会被 extern 关键字或错误地调用。

关于第一个说法:

似乎在嵌入式世界中,当 它涉及到处理硬件中断。

使用硬件中断时可以避免使用全局变量。正如其他人在 cmets 中指出的那样,嵌入式环境中的全局变量并不少见,但也不鼓励使用它们,特别是如果您有能力实现适当的封装。 This article,有人在 cmets 中提供给您的问题,实际上包含一个读者回复,该回复提供了一个很好的示例,说明无法正确实施封装(您不必走得太远,这是第一个)。

关于第二个说法:

它们也必须是可变的,这样编译器就不会优化它们,如果它 看到它们在运行的程序中从未被触及。

这句话是,让我们说“几乎是真的”。编译器知道何时需要访问变量的内存位置(写入/读取内存),因此当优化开启时,它将避免不必要的内存访问。 volatile 关键字告诉编译器不要这样做,这意味着每次使用变量时都会访问该内存位置。

需要使用 volatile 关键字的情况

  • 全局变量更新了中断
  • 多线程应用程序中的多个线程访问的全局变量
  • 内存映射外设寄存器

对于由中断更新的全局变量,volatile 关键字是必不可少的,因为中断可能随时发生,我们不想错过更新。 对于不被中断更新并且应用程序是单线程的全局变量,volatile 关键字是完全没有必要的,而且实际上会减慢您的代码速度,因为您每次都会访问该变量的内存位置!强>

有没有办法在我描述的情况下避免这些变量而不会向后弯曲太远?

这个问题的答案真的取决于。可能最重要的是您从进行这种设计更改中可以获得什么?另外,这是一个专业项目,一个用于学校,还是一个用于娱乐?

根据我作为工程师的经验,上市时间往往是公司在开发新产品时最担心的事情。通常会有一些遗留代码让你陷入困境,这些代码是在研发阶段开发的,而且它“有效”,那么为什么要花时间修复一些没有损坏的东西呢?说真的,最好是一个非常有说服力的论点,否则不要浪费你的时间。

根据我的教育经验,花时间回去实施正确的设计理念并记录它绝对是值得的,但前提是您真的有时间这样做!如果您接近最后期限,请不要冒险。如果你领先于游戏,那就去做吧。它的价值不止一种。

最后,要正确封装硬件中断的中断服务程序 (ISR),您需要将其放置在实际的设备驱动程序(CAN、UART、SPI 等)中。与 ISR 的所有通信都应仅由设备驱动程序和设备驱动程序来促进。 ISR 和设备驱动程序之间共享的变量应声明为staticvolatile。如果您需要从外部访问这些变量中的任何一个,您可以创建 setter 和 getter 作为驱动程序公共 API 的一部分。 Check this answer out for a general guideline to follow.

【讨论】:

  • 谢谢 bigwilly。你的回答指出我对什么是“全局:变量”有一些误解。我必须去阅读更多关于文件范围、编译单元、外部变量的内容需要。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2011-06-01
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多