【问题标题】:How to design a good interface for embedded system?如何为嵌入式系统设计一个好的接口?
【发布时间】:2020-02-10 22:39:48
【问题描述】:

C 代码应该在嵌入式系统上运行,例如 Arm CortexM 或类似系统。

两种API接口设计是可能的:

typedef struct { vars } t_object;
void init(t_object* p_object);
void run(t_object* p_object);

t_object my_object;
init( &my_object );
while(1)
    run( &my_object ); 

typedef struct { vars } t_object;
t_object* init( );
void run(t_object* p_object);
void deinit(t_object* p_object);

t_object* p_my_object;
p_my_object = init( );
while(1)
    run( p_my_object );

在第一种情况下,对象在堆栈上静态分配,而在第二种情况下,init() 在堆上动态分配对象。

在设计界面时选择两种方式中的一种的原因是什么?

【问题讨论】:

  • 这完全取决于程序运行的环境。这两种方法各有优缺点,具体取决于平台。
  • 通常让调用者负责被调用代码的内存管理是个坏主意。调用者可能不知道该责任,这将导致内存泄漏如果您这样做,则可能需要一些命名约定以使其明显,例如allocate_objectdelete_object 函数。
  • @Clifford 请记住,该对象将永远只有一个实例,并且它将“永远运行”。 deinit() 已提供,但因此永远不会在此处使用。
  • 这并不是真正基于意见的。有一个现有的行业事实上的标准,不透明类型。人们不使用它的唯一原因是人们不知道它。
  • @Danijel 在这种情况下,动态分配没有任何作用,init() 函数可能只是返回一个指向静态对象的指针。然后,您需要调用 init 函数来获取对该对象的引用 - 从而保证在使用前对其进行初始化。请注意,您的问题中没有提到这是一个单身人士。这是相关的,所以应该提到。

标签: c embedded


【解决方案1】:

您应该查看称为“不透明类型”或“不透明指针”的概念。它是 C 中的一种设计模式,它允许您通过利用结构的前向声明来使用私有封装。为了让它工作,你的函数必须使用指针并且分配必须在你的代码中完成。

在低端嵌入式系统中,永远不应该使用动态分配。不透明类型的分配是通过静态内存池完成的。见Static allocation of opaque data types

如何实现静态内存池的代码示例:https://stackoverflow.com/a/54999410/584518

【讨论】:

  • 我不确定是否有共识?
  • 不确定您所说的“this”是什么,但强烈避免在嵌入式系统中动态分配内存是常态。没有迫切的需要,而且负面后果太大了。
  • @Danijel 关于不透明类型,现在 MISRA-C 甚至推荐它(指令 4.8),因此它甚至是行业标准的一部分。然而,出于腐朽的传统,许多 C 程序员往往缺乏正确的程序设计和设计模式的经验。有的 K&R 读得太多了,有的从汇编来到 C,有的则是拒绝 OO 的顽固老前辈等等。
  • 我很清楚动态分配。我所说的“共识”是关于在上面的链接中使用alloca()。我不清楚这是否可以在没有alloca() 的情况下完成。
  • @Danijel 通常,您只需将自己的内存池创建为固定大小的数组,然后让构造函数从中分配 1 个对象。意味着您可以获得对象数量的上限,但嵌入式系统应该是确定性的。
【解决方案2】:

选择第一个。

通过赋予用户创建对象的责任,他可以根据需要使用静态、自动或动态。实际使用和单元测试使用可以使用不同的分配方案。

如果您使用的是嵌入式独立系统,其中内存以千字节而不是兆字节计算,那么动态内存分配通常是您不需要的奢侈品。通常静态存储更适合“永恒”对象,而堆栈适合临时对象。

【讨论】:

    猜你喜欢
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多