用于中断安全的 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 char
或unsigned 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 文档不是免费的,但它正在成为行业标准。
再说一次,我不是开发人员而是木工,所以我的问题可能很愚蠢。
我忘记了一些非常重要的事情我必须使用 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 char
或unsigned 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 文档不是免费的,但它正在成为行业标准。