57

我一直很想知道是否可以将 Haskell 的强大功能应用于嵌入式实时世界,并且在谷歌搜索中找到了Atom包。我假设在复杂的情况下,代码可能具有所有经典的 C 错误 - 崩溃、内存损坏等,然后需要追溯到导致它们的原始 Haskell 代码。所以,这是问题的第一部分:“如果你有使用 Atom 的经验,你是如何处理调试编译 C 代码中的低级错误并在 Haskell 原始代码中修复它们的任务的?”

我搜索了更多关于 Atom 的示例,这篇博文提到了生成的 C 代码 22KLOC(显然没有代码:),包含的示例是一个玩具。thisthis引用有一些更实用的代码,但这就是结束的地方。我在主题中加上“相当大”的原因是,如果你能分享你在 300KLOC+ 范围内使用生成的 C 代码的经验,我最感兴趣。

由于我是 Haskell 新手,显然由于我未知的未知,我可能没有找到其他方法,因此将非常感谢该领域的任何其他自我教育指针 - 这是问题的第二部分 - “在 Haskell 中进行实时开发的其他一些实用方法(如果)是什么?”。如果多核也在图片中,那是一个额外的加分:-)

(关于为此目的使用 Haskell 本身:从我在这篇博客文章中读到的内容,Haskell 中的垃圾收集和惰性使其在调度方面相当不确定,但可能在两年内发生了一些变化。关于 SO的真实世界 Haskell 编程问题是我能找到的最接近这个主题的)

注意:上面的“实时”会更接近于“硬实时”——我很好奇是否可以确保主任务不执行时的暂停时间低于 0.5 毫秒。

4

5 回答 5

52

在 Galois,我们使用 Haskell 做两件事:

  • 软实时(操作系统设备层、网络),其中 1-5 毫秒的响应时间是合理的。GHC 生成快速代码,并为调整垃圾收集器和调度程序以获得正确的时间提供大量支持。
  • 对于真正的实时系统,EDSL 用于为提供更强时序保证的其他语言生成代码。例如 Cryptol、Atom 和 Copilot。

所以要小心区分 EDSL(Copilot 或 Atom)和宿主语言(Haskell)。


关键系统的一些例子,在某些情况下,实时系统,无论是编写的还是从 Haskell 生成的,由 Galois 制作。

EDSL

系统

  • HaLVM——用于嵌入式和移动应用程序的轻量级微内核
  • TSE——跨域(安全级别)网络设备
于 2009-08-12T18:15:26.487 回答
6

需要很长时间才能有一个适合小内存的 Haskell 系统,并且可以保证亚毫秒级的暂停时间。Haskell 实现者社区似乎对这种目标不感兴趣。

使用 Haskell 或类似 Haskell 的东西来编译成非常有效的东西是很有趣的;例如,Bluespec编译为硬件。

我认为它不能满足您的需求,但如果您对函数式编程和嵌入式系统感兴趣,您应该了解Erlang

于 2009-08-12T03:36:35.313 回答
6

安德鲁,

是的,通过将生成的代码返回到原始源来调试问题可能很棘手。Atom 提供了一种探测内部表达式的方法,然后由用户决定如何处理这些探测。对于车辆测试,我们构建了一个发射器(在 Atom 中)并通过 CAN 总线将探头输出。然后我们可以捕获这些数据,对其进行格式化,然后使用 GTKWave 等工具在后处理或实时中查看它。对于软件仿真,探针的处理方式不同。不是从 CAN 协议获取探测数据,而是对 C 代码进行挂钩以直接提升探测值。然后在单元测试框架(与 Atom 一起分发)中使用探测值来确定测试是通过还是失败并计算模拟覆盖率。

于 2009-10-17T13:14:17.990 回答
4

我不认为 Haskell 或其他垃圾收集语言非常适合硬实时系统,因为 GC 倾向于将它们的运行时摊销为短暂的暂停。

用 Atom 编写并不完全是用 Haskell 编程,因为 Haskell 在这里可以被视为纯粹是您正在编写的实际程序的预处理器。

我认为 Haskell 是一个很棒的预处理器,使用像 Atom 这样的 DSEL 可能是创建大型硬实时系统的好方法,但我不知道 Atom 是否符合要求。如果没有,我很确定有可能(并且我鼓励任何这样做的人!)实现一个 DSEL。

拥有一个非常强大的预处理器(如 Haskell)为一种低级语言打开了一个巨大的机会之窗,可以通过代码生成来实现抽象,当实现为 C 代码文本生成器时,这些抽象要笨拙得多。

于 2009-08-12T12:31:05.410 回答
4

我一直在玩弄 Atom。这很酷,但我认为它最适合小型系统。是的,它在卡车和公共汽车上运行并实现现实世界的关键应用程序,但这并不意味着这些应用程序一定很大或很复杂。它确实适用于硬实时应用程序,并且竭尽全力使每次操作都花费完全相同的时间。例如,不是 if/else 语句有条件地执行可能在运行时间上不同的两个代码分支之一,它有一个“mux”语句,它总是在有条件地选择两个计算值之一之前执行两个分支(所以总无论选择哪个值,执行时间都相同)。除了内置类型之外,它没有任何重要的类型系统(类似于 C' s) 通过 Atom monad 传递的 GADT 值强制执行。作者正在开发一个分析输出 C 代码的静态验证工具,它非常酷(它使用 SMT 求解器),但我认为 Atom 将受益于更多的源代码级功能和检查。即使在我的玩具大小的应用程序(LED 手电筒控制器)中,我也犯了一些新手错误,这些包经验丰富的人可能会避免,但这导致了错误的输出代码,我宁愿被编译器捕获而不是通过测试。另一方面,它仍然是 0.1 版。所以毫无疑问,改进即将到来。但我认为 Atom 将受益于更多的源代码级功能和检查。即使在我的玩具大小的应用程序(LED 手电筒控制器)中,我也犯了一些新手错误,这些包经验丰富的人可能会避免,但这导致了错误的输出代码,我宁愿被编译器捕获而不是通过测试。另一方面,它仍然是 0.1 版。所以毫无疑问,改进即将到来。但我认为 Atom 将受益于更多的源代码级功能和检查。即使在我的玩具大小的应用程序(LED 手电筒控制器)中,我也犯了一些新手错误,这些包经验丰富的人可能会避免,但这导致了错误的输出代码,我宁愿被编译器捕获而不是通过测试。另一方面,它仍然是 0.1 版。所以毫无疑问,改进即将到来。

于 2010-01-19T22:48:42.400 回答