弹性内存分配在IOT中的重要性
一般而言,开发人员不太会考虑内存分配。毕竟,现代计算机、平板电脑和服务器的内存如此之大,通常看起来像是无限的资源。而且,内存分配失败或错误不太可能发生,即使出现问题,系统通常默认退出程序。
然而,当涉及到物联网(IoT)时,情况大有不同。在这些嵌入式连接设备中,内存会变得更加抢手,多个程序会争夺有限的资源;而且集成系统越小,内存也更小。因此,最好将其视为有限的资源并保守使用。
正是在这种背景下,内存分配(malloc)在IOT行业中非常重要。malloc是计算机在运行程序或进程时动态分配内存的过程。尤其是对于连接到互联网的设备,正确处理malloc直接决定其性能好坏。
下面,让我们来看看开发人员如何在他们的内存分配方法中弹性设计,以及这对未来的物联网设备意味着什么。
1、内存分配和物联网设备
传统上,内存分配(malloc)经常不用于嵌入式系统。这是因为较旧的设备通常不会连接到互联网,因此计算的内存需求并不大。
但是,这些较旧的设备在系统启动时创建了一个资源池来分配资源。一个资源可以是一个连接,一个系统可以配置n个来自静态分配池的连接。
在未连接Internet的系统中,系统的状态通常受到一定程度的限制,因此更容易估计内存分配malloc的上限。但是,一旦嵌入式系统连接到互联网,这种情况就会发生巨大变化。
例如,一个设备需要计算多个连接,并且每个连接都有不同的内存需求,这取决于连接的用途。每个连接上的数据流所需的缓冲内存取决于连接的延迟,通过使用某些概率函数或其他网络连接的行为方式来处理数据包丢失,从而获得一定的吞吐量。
通常这在现代高端系统上不是问题。但是,开发人员在嵌入式环境中面临有限的内存资源,我们不能简单地假设有足够的内存。
这就是为什么在物联网嵌入式开发中,考虑如何规避内存分配错误或者malloc失败是非常重要的。
2、现代嵌入式系统和malloc
在现代的嵌入式系统中,malloc的使用频率更高,许多嵌入式系统和平台都有不错的malloc实现。这种转变的原因是现代连接的嵌入式系统执行更多的任务,通常无法静态地为所有程序的执行分配所需的最大资源。
在现代互联嵌入式系统中积极使用malloc,这种转变需要更彻底和系统的软件测试来发现错误。
通常,malloc错误不会系统测试,因为它发生的概率极低,不值得这么去做。正因为malloc错误非常罕见,所以其漏洞在发现之前可能已存在数年。
3、mallocfail工具:如何测试错误
令人高兴的是,开发人员可以利用软件来测试分配错误。有一种新颖的方法是通过运行一个程序,在发生分配的所有执行路径中注入分配错误。这可以通过mallocfail工具实现。
顾名思义,Mallocfail以确定的方式测试malloc错误。该工具不是随机测试,而是通过不同的控制路径自动枚举malloc错误。它的灵感来自于Stack Overflow。
简而言之,此工具使用自定义版本分配器malloc、calloc和realloc。每次运行自定义分配器时,都会使用libbacktrace获取当前线程的函数调用堆栈,生成对应的 sha256 哈希值。然后,该工具检查是否出现新的哈希值。如果出现从未见过的哈希(特定的调用堆栈),则内存分配malloc失败,并将哈希值存储在内存中写入磁盘;如果之前见过,则正常调用分配器libc版本。每次程序启动时,已见过的哈希值都会从磁盘加载。
这是我第一手使用过的东西,发现非常有用。例如,我们在嵌入式边缘软件开发工具包上成功测试了mallocfail。该工具成功识别了SDK及其第三方库中的一些问题,而且它们的问题现已修复了。
4、处理malloc问题
在复杂的系统中,处理分配错误可能有点棘手。例如,处理一个事件需要考虑分配多少内存。当然,解决方案有很多种。最重要的是分配必要的内存,以便在分配失败时可以将错误传递回程序,不至于某些问题被悄无声息的隐藏其中。
处理malloc 失败的能力是我们团队经常考虑的问题。当然,这在其他设备上可能并没有什么,但它会在连接到互联网的嵌入式设备上引起大问题。
因此,我们的 SDK 会计算限制某些资源的功能,包括连接、流、缓冲区等。这样,系统配置限制使用的内存量,以免发生malloc错误。
通常,系统内存不足会导致系统难以运行。因此,通过限制同时发生的功能/任务,降低内存分配错误的概率是很有意义的。
回首过去,我已经在这个互联网设备领域工作了二十年,期待同行开发人员在现代嵌入式开发中,采用最佳的malloc实践。
建议您深入考虑嵌入式设备如何解决内存分配问题,积极研究使用内存的最有效方式。尽可能使用动态内存分配和mallocfail测试进行开发,因为它对嵌入式物联网设备的性能及其可用性至关重要。