用于中断安全的 malloc 替代方案

malloc alternative for interrupt safety

再说一次,我不是开发人员而是木工,所以我的问题可能很愚蠢。

我忘记了一些非常重要的事情我必须使用 gcc-3.8 进行编译,因为我正在使用的原始代码无法使用较新的版本进行编译。我完全忘了谈论那个,抱歉。

我正在将数据从工具发送到自主机器人。 机器人以无符号字符形式接收数据* 我看了很多书,似乎 malloc 不是中断安全的。

由于机器人可能会做坏事和危险的事情,所以我尽量保证每个部件的安全(至少尽我所能)。

这个 malloc 发生在接收到的数据引发的中断之后。 这个代码段现在让我很难保证它的安全,而且我的语法可能很糟糕..

char* _Xp = (char*) malloc(strlen((char*)_X)*sizeof(char));
strcpy(_Xp, (char*)_X);

1) malloc 真的不是中断安全的吗?我找到的信息是2004年的。

2) 有没有更有效的初始化缓冲区的方法?

3) 为什么unsigned char是"bad"? (阅读相关内容)。

4) 最后一个问题是strcpy 也不是中断安全的吗?我读到的资料在这一点上有所不同。

===== 回答一些问题:

机器人没有操作系统,目标是 25Mhz 的 STR911FFM44(如果有帮助)

输入数组均以 nul 结尾。

代码不在中断处理程序中,而是在无限循环中,并且只有在 IrHandler 为其设置标志时才被处理。

我不知道数据流的速率"hard code"是否安全。但中断应该在 [500ms 到 1500ms] 之间。

1) is malloc really not interrupt safe?

malloc 访问和修改全局资源,即您 运行 程序的公共内存池。如果访问发生在两个不同步的地方,例如您的正常程序流和 ISR1,那么它可能会弄乱池。如果您的 ISR 不调用 malloc 本身,那将不是问题。

如果是这样,您需要建立一个系统来防止此类重新进入 malloc。例如,将对 malloc 的调用包装在一个关闭中断处理的函数中,然后再打开。

2) is there a more efficient way to initialize the buffer?

如果您需要一个具有分配存储持续时间的缓冲区(即您决定其生命周期何时结束,而不是它分配的范围),那么实际上没有标准的 C 替代方案。顺便说一下,sizeof(char) 总是 1,所以不需要指定它。 And since C allows implicit conversion of pointer types from void*,调用至少可以美化一下2:

char* _Xp = malloc(strlen((char*)_X));

3) why are unsigned char "bad"?

他们还不错。事实上当你需要确切知道字符类型是否有符号时,你必须使用signed charunsigned char。常规 char 可以在一个平台上签名并在另一个平台上取消签名。


1 中断服务例程。
2 C有一个reserved identifiers的概念。特别是,任何以下划线开头后跟大写字母的标识符始终被保留。因此,重命名您的变量可能有助于提高可移植性。

首先你说你用的是裸机单片机,所以malloc never makes sense。它不是 PC - 您不会与其他任何人共享您的 RAM。所以 malloc 的所有危险和缺点甚至都不会进入讨论,因为 malloc 对您来说根本没有任何意义。

1) is malloc really not interrupt safe? information I found are from 2004.
4) last question is strcpy also not interrupt safe? sources I read differ on that point.

在 ISR 和主应用程序之间使用共享资源的函数都不是中断安全的。您应该避免从 ISR 调用库函数,它们应该保持最少。

ISR 和调用者之间共享的所有数据都必须小心处理。您必须确保单个对象的原子访问。您必须 声明诸如volatile 的变量以防止优化器错误。您可能必须使用信号量或其他同步方式。这适用于所有此类数据,无论您是自己更改还是通过库函数更改。

不执行上述所有操作将导致非常神秘和微妙的错误,导致数据损坏、竞争条件或代码永远不会执行。总的来说,由于所有这些额外的复杂性,中断总是很难处理。仅当您的实时要求没有其他选择时才使用它们。

2) is there a more efficient way to initialize the buffer?

是的,使用数组。 static char _Xp [LARGE_ENOUGH_FOR_WORST_CASE]; 通常将此类缓冲区保存在 .data 段中而不是堆栈中是个好主意,因此使用 static 关键字。

3) why are unsigned char "bad"? (read something about that).

他们本身并没有什么不好。但是,不同的 char 类型是有问题的,因为理论上它们可以有 8 位以外的其他大小。更糟糕的是,没有 signed/unsigned 的 char 具有 实现定义的符号 ,这意味着它可能被签名 未签名,具体取决于编译器。这意味着你应该 永远不要 使用 char 类型来存储除文本字符串之外的任何其他内容。

如果您需要一个变量类型来保存数据字节,请始终使用 stdint.h 中的 uint8_t

As the robot could do bad & dangerous things, I try to make every parts safe (at least as much as I can).

为嵌入式系统编写安全软件是一项高素质的任务。我不建议任何全职嵌入式固件编程经验少于 5 年的人考虑它,除非你的团队中至少有一位经验丰富的 C 老手并且所有代码都通过了同行评审和静态分析.

听起来您通读 MISRA-C:2012 编码指南会受益匪浅。它是 C 语言的一个安全子集,旨在用于对安全至关重要的应用程序,或任何形式的错误严重的应用程序。不幸的是,MISRA-C 文档不是免费的,但它正在成为行业标准。