是否可以用Java编写设备驱动程序?

时间:2009-03-25 22:09:14

标签: java operating-system device-driver

简介

我听说过用Java编写设备驱动程序(听说“用我的耳朵”,而不是来自互联网),并且想知道......我一直认为设备驱动程序在操作系统级别上运行,因此必须用与OS相同的语言(因此大多是CI假设)

问题

  1. 我一般都错了 假设呢? (似乎是这样)
  2. “外星人”中的司机怎么样? 在OS中使用语言?
  3. 有什么要求(来自a 编程语言的观点) 对于设备驱动程序无论如何?
  4. 感谢您阅读

13 个答案:

答案 0 :(得分:20)

有几种方法可以做到。

首先,在“OS级别”运行的代码不需要使用与OS相同的语言编写。它只需要能够与OS代码链接在一起。实际上,所有语言都可以与C进行互操作,这实际上就是所需要的。

语言方面,技术上没有问题。 Java函数可以调用C函数,C函数可以调用Java函数。如果操作系统不是用C语言编写的(比如说,为了论证它是用C ++编写的),那么OS C ++代码可以调用一些中间的C代码,它们转发到Java,反之亦然。 C几乎是编程的通用语言

程序编译完成后(到本机代码),其源语言不再相关。无论在编译之前编写源代码的语言是什么,汇编程序看起来都大致相同。只要您使用与操作系统相同的调用约定,就没问题了。

更大的问题是运行时支持。操作系统中没有很多软件服务可用。例如,通常没有Java虚拟机。 (没有理由在技术上不可能,但通常,但通常,假设它不存在是安全的。)

不幸的是,在其“默认”表示中,作为Java字节码,Java程序需要许多基础结构。它需要Java VM来解释和JIT字节码,它需要类库等等。

但是有两种解决方法:

  • 在内核中支持Java。这将是一个不寻常的步骤,但它可以完成。
  • 或者将Java源代码编译为本机格式。 Java程序不必编译为Java字节码。您可以将其编译为x86汇编程序。您使用的任何类库都是如此。那些也可以编译到汇编程序。当然,Java类库的某些部分需要某些不可用的操作系统功能,但是可以避免使用这些类。

是的,可以做到。但这不是直截了当的,也不清楚你会得到什么。

当然另一个问题可能是Java不会让你访问任意内存位置,这会使很多硬件通信变得非常棘手。但这也可以通过调用非常简单的C函数来解决,这些函数只是将相关的内存区域作为Java的数组返回来工作。

答案 1 :(得分:19)

Writing Solaris Device Drivers in Java涵盖了用Java编写的A RAM磁盘设备。

Another one for Linux。更深入地了解为什么你可能想要Java中的DD(因为有些人对其他帖子和评论的外观感到疑惑)

答案 2 :(得分:4)

这不是不可能,但可能很难,可能没什么意义。

可能是这样,因为Java是一种普通的编程语言,只要你有办法访问数据,就没问题了。通常在现代操作系统中,内核有一个层,允许以某种方式对硬件进行原始访问。用户空间中也存在驱动程序,至少用户空间部分在Java中实现应该没有问题。

它可能没有多大意义,因为内核必须启动JVM才能执行驱动程序。此外,JVM实现通常会占用大量内存。

您还可以使用编译的Java代码在平台上本机执行(而不是在JVM的帮助下)。这通常效率不高,但它可能适合设备驱动程序。

问题是,在Java中实现驱动程序是否有意义?或者以另一种方式说明:如果您使用Java实现驱动程序而不是其他替代方案,您希望获得的好处是什么?如果你能回答这个问题,你应该找到一种方法使它成为可能。

最后提示JNode,这是一个试图完全基于Java实现完整操作系统的项目。

答案 3 :(得分:4)

设备驱动程序可能很多东西

我实际上是用java编写设备驱动程序:工业设备驱动程序,例如秤或称重设备,包装机,条形码扫描仪,称重桥,包装盒和盒式打印机...... Java在这里是一个非常好的选择。

Some examples

工业设备与您的家庭/办公设备(例如扫描仪,打印机)非常不同。特别是在制造业(例如食品)中,公司越来越多地选择运行MES应用程序的集中式服务器(例如用Java开发) MES服务器需要与生产线的设备连接,但也包含业务逻辑:Java是一种可以兼顾两者的语言。

如果您的家庭/办公设备通常内置于您的计算机或通过USB电缆连接,这些工业设备通常使用以太网或RS232连接器。因此,从本质上讲,几乎所有语言能做好这件事。

此领域尚未实现太多标准化。大多数供应商更愿意为其设备创建自己的协议。毕竟他们是硬件构建者,而不是软件天才。结果是协议的多样性很高。一些供应商更喜欢简单的纯文本协议,但是其他供应商更喜欢具有CRC代码,成帧的复杂二进制协议......有时他们喜欢堆叠多个协议(例如,在OPC层之上的供应商特定的握手算法)。 强大的OOP语言在这里有很多优势。

  

E.g。我以100毫秒/周期的连续速度看过java打印。这包括生成一个独特的标签,将其发送到打印机,接收确认,将其打印在纸上并使用气压将其应用到产品中。

总之,java的力量:

  • 这对于作为复杂接口的业务逻辑都很有用。
  • 与C套接字通信一样可靠。
  • 有些驱动程序可以从Java的OOP电源中受益。
  • Java足够快。

答案 4 :(得分:3)

您是否听说过JDDK

的引用

在Java中100%编写设备驱动程序在没有本机代码的情况下是不可能的,以提供(1)特定于操作系统的驱动程序入口点和约定,以及(2)JVM实例之间的交互。 JVM实例可以“在进程中”启动(并且“进程内”可能具有不同的含义,具体取决于操作系统以及驱动程序是内核模式还是用户模式驱动程序),或者作为单独的用户域薄的本机驱动程序适配层可以与之通信的过程,并且所述驱动程序适配层可以卸载实际的用户土地工作。

答案 5 :(得分:3)

您的设备驱动程序视图太窄。

我已经在汽车应用中的MOST上编写了这样的设备驱动程序。如果Java有一个像样的USB库,更广泛的用途可能是USB设备的驱动程序。

在这些情况下,有一个通用的低级协议,用本机代码处理,Java驱动程序处理设备细节(数据格式,状态机......)。

答案 6 :(得分:2)

可能将Java代码编译为硬件本机(即非JVM字节码)指令。例如,请参阅GCJ。有了这个,你就可以比以前更接近编译设备驱动程序了。

但我不知道它有多实用。

答案 7 :(得分:2)

可能?

是的,但仅限于特殊情况。因为您可以用Java和C#编写操作系统,然后,应该能够为它编写设备驱动程序。这些驱动程序和操作系统的内存将是巨大的。

<强>可能的吗

不太可能。至少不是在Windows或MacOS甚至Linux的世界......至少不会很快。因为像C#和Java这样的语言依赖于CLR和JVM。这些语言的工作方式意味着它们无法有效地加载到ring0中。

此外,如果在设备驱动程序中使用托管语言,性能影响会相当大。

答案 8 :(得分:2)

为了动力,请记住,有很多快速语言比C语言更适合编程;它们可能没有C那么快,但它们是安全的语言:如果你犯了一个错误,你就不会得到未定义的行为。并且“未定义的行为”包括执行由格式化HD的攻击者提供的任意代码。 许多函数式语言通常都编译为本机代码。

设备驱动程序包含操作系统内核中的大多数错误 - 我知道对于Linux(Linus Torvalds和其他人一直这样说)我听说过Windows。对于磁盘或以太网驱动程序,您需要一流的性能,而在Linux驱动程序中, 10G以太网或SSD磁盘的瓶颈,大多数驱动程序不需要那么快的速度 - 所有计算机都在等待以同样的速度。

这就是为什么有各种项目允许编写在内核之外运行的驱动程序,即使这会导致速度减慢;当你能做到这一点时,你可以使用你想要的任何语言;然后你需要为你使用的硬件控制库进行Java绑定 - 如果你用C编写驱动程序,你仍然会有一个带有C绑定的库。

对于内核模式适当的驱动程序,我还没有提到过两个问题:

  • 垃圾收集,这是一个艰难的要求。你需要编写一个内核垃圾收集器;一些GC算法依赖于虚拟内存,您无法使用它们。此外,您可能需要扫描整个OS内存以找到GC的根。最后,我只相信一种保证(软)实时GC的算法,这会使开销更大。 阅读在Linux之上提到的关于Java设备驱动程序的论文,他们只是放弃了,并要求程序员手动释放内存。他们试图争辩说这不会危及安全,但我不认为他们的论点是令人信服的 - 他们是否理解垃圾收集是否需要安全语言甚至不清楚。

  • 反射和类加载。即使在运行本机代码时,完整的Java实现也需要能够加载新代码。这是一个你可以避免使用的库,但如果你在内核中有一个解释器或JIT编译器(并且没有真正的原因让技术上不可能)。

  • 性能。关于Linux上的JVM的论文非常糟糕,它们的性能数据并不令人信服 - 事实上,它们测试的是USB 1.1网络驱动程序,然后表明性能并不是那么糟糕!但是,如果付出足够的努力,肯定可以做得更好。

最后两件事:

  • 我想提一下Singularity,这是一个用C#变体编写的完整操作系统,只有一个母语的硬件抽象层。
  • 关于picoJava,使用它是一个坏主意,除非你的系统是一个真正受内存限制的系统,比如智能卡。 Cliff Click已经解释了原因:它可以提供更好的性能来编写一个好的JIT,而现在甚至智能手机都能支持它。

答案 9 :(得分:1)

设备驱动程序必须使用可在内核中执行的语言编写,或者编译到其中,或者在运行时作为模块加载。这通常会妨碍用Java编写设备驱动程序,但我认为理论上你可以在设备驱动程序中实现JVM并让它执行Java代码。并不是说任何理智的人都会这样做。

在Linux上有几个文件系统的用户域(即非内核)实现,它们使用一个称为(fuse)的通用抽象层,允许用户域程序实现通常在内核中完成的事情。

答案 10 :(得分:1)

Windows Driver Foundation(WDF)是一个Microsoft API,它允许写入UserKernel模式设备驱动程序。这是在今天完成的,它现在与w2k及更高版本兼容(曾经没有将w2k作为支持的目标)。没有理由不能让JNI调用在JRE中做一些工作。 。 。 (假设JNI仍然是从C / C ++调用Java的方式......我的知识在那个领域已经过时了)。这可能是一种有趣的方法,让高级算法直接咀嚼USB管道中的数据,以实现这种效果。 。 。很酷的东西!

答案 11 :(得分:1)

PCIe用户空间设备驱动程序可以用Pure Java编写。有关基于内存的直接硬件访问的详细信息,请参阅JVerbs。这是一种可用于创建高性能系统的技术。

您可以检查PCI总线以确定给定设备的内存区域,它具有的端口等。内存区域可以映射到JVM的进程中。

当然,您自己负责实施一切

我并不容易说。我说可能。 ;)

另请参阅Device Drivers in User Space,其中讨论了使用UIO框架构建用户空间驱动程序。

答案 12 :(得分:-1)

首先,请注意我不是设备驱动程序方面的专家(虽然我当天写了几篇文章),更不用说Java专家了。

让我们留下这样一个事实:用高级语言编写设备驱动程序并不是一个好主意(出于性能和可能的许多其他原因)暂时搁置,并回答你的问题。

可以以几乎任何语言编写设备驱动程序,至少在理论上是这样。

但是,大多数设备驱动程序需要执行大量低级操作,例如使用操作系统API和系统调用处理中断和与操作系统通信,我相信你不能用Java做

但是,如果您的设备使用串行端口或USB进行通信,并且操作系统不一定需要知道设备(只有您的应用程序将访问设备*),那么您可以编写任何语言的驱动程序,提供访问设备的必要方法。

例如,您可能无法用Java编写SCSI卡驱动程序,但您可以为专有控制设备,USB熔岩灯,许可证加密狗等编写驱动程序。

*这里显而易见的问题当然是否算作一个驱动因素?