深入探究 D 语言嵌入式编程

27

我很喜欢我所读的关于 D 语言的许多内容。

  • 统一的文档(这将使我的工作更加容易。)
  • 内置测试能力。
  • 语言中带有调试代码支持。
  • 向前声明。(我总是认为声明相同的函数两次很愚蠢。)
  • 内置替换预处理器的功能。
  • 模块化
  • 使用 Typedef 进行正确的类型检查而不是别名。
  • 嵌套函数。(咳咳 PASCAL 咳咳
  • 输入和输出参数。(多明显啊!)
  • 支持低级编程 - 嵌入式系统,哦耶!

然而:

  • D 是否支持在没有运行操作系统的嵌入式系统中运行?
  • 它明确声明不支持 16 位处理器是否完全排除了在此类设备上运行的嵌入式应用程序?有时你不需要一把锤子来解决你的问题。
  • 垃圾收集在 Windows 或 Linux 上很棒,但不幸的是,嵌入式应用程序有时必须进行显式内存管理。
  • 数组边界检查,你爱它,你恨它。对于设计保证非常好,但不一定适用于性能问题。
  • 在嵌入式系统上,不运行操作系统时,多线程支持有什么影响?我们有一个客户甚至不喜欢中断。更不用说操作系统/多线程了。
  • 是否有适用于嵌入式系统的 D-Lite 版本?

所以基本上,D 语言适合于只有几兆字节(有时少于一兆字节),不运行操作系统,需要在编译时了解最大内存使用量(根据要求)且可能比 32 位处理器小得多的嵌入式系统吗?

我对其中一些功能非常感兴趣,但我有这样的印象,它是面向桌面应用程序开发人员的。

什么具体因素使其不适合16位实现?(假设16位架构可以寻址足够的存储器来保存运行时数据,无论是在闪存还是RAM中。)使用库代码仍然可以计算32位值,尽管速度较慢且需要更多的操作。


larsivi 是 Tango 库的开发人员之一,因此也要认真考虑他的答案。 - quark
1
哦,“D-Lite”是个很棒的名字 :)。我希望有人会使用它。 - quark
1
可能是重复问题:https://dev59.com/snNA5IYBdhLWcg3wC5NR - Daniel Earwicker
这很相似,但是更加具体。 - NoMoreZealots
此外,嵌入式编程并不一定意味着实时编程。 - larsivi
我想你是对的,但我还没有运行在非嵌入式系统上的运气。嵌入式系统意味着专用系统,不用于通用计算应用程序。例如,大多数情况下是一个愚蠢的手机。而iPhone则不同,它是一台带有电话功能的掌上电脑。该死,我仍然有一些旧的开发系统,规格比iPhone低,我们无法摆脱它们,因为这些工具无法在现代PC上运行。 - NoMoreZealots
3个回答

13

我必须说,对于这个问题的简短回答是“不行”。

  • 如果你的机器是16位的,那么使用D语言将会面临很大的问题-它明确不是为此而设计的。
  • D语言本身并不轻便,它会生成许多运行时类型信息通常都被链接到你的应用程序中,并且这些信息对于类型安全的可变参数(以及标准格式化功能,无论是Tango还是Phobos)也是必需的。这意味着即使是最小的应用程序在文件大小方面也有惊人的表现,并且可能因此使得低RAM系统无法使用D语言。此外,带有运行时的共享库的D语言(可以缓解其中一些问题)也经过了较少的测试。
  • 所有当前的D语言库都需要底层的C标准库,因此通常也需要一个操作系统,所以这也不利于使用D语言。然而,目前确实存在一些用D语言编写的实验性内核,因此它并非从根本上不可能。只是截至今天,没有任何相应的库。

我个人希望看到你成功,但我怀疑这将不是易事。


我们有一些客户非常关注程序验证和程序正确性。D语言的一些特性似乎非常适合这个需求。至于“标准C库”,大多数嵌入式开发系统都有一定程度的支持,他们可能会要求您填写低级别的I/O支持,有点像回调函数,但通常您不需要进行文件访问。 - NoMoreZealots
一个"轻量级"库集合可以消除一些重量级。我不需要很多适用于基于操作系统的系统的功能。然而,ADA也支持多任务处理,这意味着在嵌入式系统上需要一个大型的运行时支持库。嵌入式ADA运行时实际上配备了一个操作系统来支持多任务处理。 - NoMoreZealots
如果你愿意/有能力投入一些努力,我会很有兴趣合作。 - larsivi
愿意,是的。能力方面,在我熟悉这门语言之后可能可以做到。目前,我的理解还仅限于“表面”材料。我需要在一个可以“玩耍”的环境中安装它,并让语法和功能深入人心。 - NoMoreZealots
2
@larsivi 这在2014年仍然是现状吗? - RedX
@RedX 我不太清楚,最近几年我并没有涉足D语言。 - larsivi

7
首先阅读larsivi's answer。他曾参与D运行时的开发,对自己所说的内容非常了解。
我只是想补充一下:你所问的一些问题已经有了解决方案。虽然不是完美的,但还是可以做到一部分的,供您参考:
垃圾回收在Windows或Linux上很好,但是不幸的是,嵌入式应用程序有时必须进行显式内存管理。
您可以关闭垃圾回收。一些实验性的D操作系统已经这样做了。请查看std.gc模块,特别是std.gc.disable。请注意,您不需要使用new来分配内存:您可以使用mallocfree。甚至数组也可以使用它来分配,您只需要使用切片将D数组附加到分配的内存上即可。
数组边界检查,你既喜欢它又讨厌它。它对于设计保障非常有用,但在性能问题上并不总是允许的。数组规范明确要求编译器允许关闭边界检查(请参见“实现说明”)。gdc提供了-fno-bounds-check选项,在dmd中使用-release应该可以禁用它。
嵌入式系统在不运行操作系统的情况下,对于多线程支持会有什么影响?我们有一个客户甚至不喜欢中断。更别说操作系统/多线程了。这一点我不太清楚,但考虑到大多数C运行时都允许关闭多线程,似乎可以让D运行时也禁用它。无论目前是否容易或可能,我都无法告诉你。

1
我读了他的帖子。事实上,我甚至还评论了它!:) 在编译器中禁用边界检查是好的,但我认为指定关闭特定代码段的边界检查并在其他不需要时间关键性的代码段中使用它以提高安全性会更好。在大多数情况下,我甚至不使用malloc,而是通过链接器将其预分配到特定的内存地址(即内部与外部RAM块)。 - NoMoreZealots
1
我确实阅读了他的帖子。抱歉Pete,我并不是要表现得很冲动!当我发帖时,你还没有评论(我们同时在编辑)。但我的主要意思是提醒其他人阅读他的回答,并且在StackOverflow上,答案的顺序可能会被重新排列。 - quark
指定特定代码段关闭边界检查。我同意。我不知道是否有相关的功能。 - quark
如果您停用运行时的GC(垃圾回收)和线程部分,那么将相对容易地进行单线程更改。但是,取消GC会排除某些数组语言功能的使用。另一个选择是将GC重写为简单的按需服务,以便应用程序始终直接控制它,无论是用于分配还是收集目的。 - larsivi
Pete:是的,实际的运行时是用 D 语言编写的,但它的接口是 C 接口,以允许在普遍存在的 C 运行时上进行引导实现。请查看 http://www.dsource.org/projects/druntime。 - quark
显示剩余3条评论

4
这个问题的答案已经过时:
D可以交叉编译为ARM LinuxARM Cortex-M。一些项目旨在创建Cortex-M架构的库,如MiniLibD for STM32或者使用通用库的项目for STM32。(你可以在ARM Cortex-M上使用D实现自己的最小操作系统。)
声明不支持16位处理器是否完全排除了它在运行此类机器的嵌入式应用程序中的使用?有时候你不需要用锤子来解决问题。

不,见上面的答案...(但我不认为比Cortex-M更小的架构会在不久的将来得到支持。)

垃圾回收在Windows或Linux上很好用,但是,不幸的是,嵌入式应用程序有时必须进行显式内存管理。

您可以编写无垃圾回收代码。(D基金会似乎旨在实现“无GC兼容”标准库Phobos,但这还在进行中。)

数组边界检查,你喜欢它,你讨厌它。对于设计保证非常好,但对于性能问题并不总是可允许的。

(正如您所说,这取决于您的“个人口味”和设计决策。但我会假设由于D编译器开发人员的背景和D的设计目标,对于边界检查的可接受性能开销。)

在没有运行操作系统的嵌入式系统上,多线程支持有什么影响?我们有一个客户甚至不喜欢中断。更不用说操作系统/多线程了。

问题是什么?可以使用D语言的功能来实现多线程,例如在这个问题中解释的那样。顺便说一句:如果你想要使用中断,请考虑Cortex-M3的"hello world"项目

是否有适用于嵌入式系统的D-Lite版本?

D语言的SafeD子集面向嵌入式领域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接