Можно ли закодировать драйвер устройства в Java?
================================================

 Введение
---------

Я слышал что-то о написании драйверов устройств на Java (слышал, как в "ушах", а не из Интернета) и задавался вопросом... Я всегда думал, что драйверы устройств работают на уровне операционной системы и поэтому должны быть написаны в на том же языке, что и ОС (таким образом, в основном, CI)   
  

 Вопросы
--------

* Я вообще ошибаюсь в этом
предположение? (кажется, так)
* Как водитель в "чужой"
язык в ОС?
* Каковы требования (от
язык программирования)
для драйвера устройства в любом случае?

Спасибо за чтение

 

Есть несколько способов сделать это.

Во-первых, код, работающий на "уровне ОС", не обязательно должен быть написан на том же языке, что и ОС. Он просто должен быть связан с кодом ОС. Практически все языки могут взаимодействовать с C, и это действительно все, что нужно.

Таким образом, с точки зрения языка, технически нет проблем. Функции Java могут вызывать функции C, а функции C могут вызывать функции Java. И если ОС не написана на C (скажем, ради аргумента, написанного на С++), тогда код ОС С++ может вызывать некоторый промежуточный код C, который пересылается на вашу Java, и наоборот. C в значительной степени является языком программирования.

Как только программа была скомпилирована (для собственного кода), ее исходный язык больше не имеет значения. Ассемблер выглядит примерно так же, независимо от того, на каком языке был написан исходный код перед компиляцией. Пока вы используете то же соглашение о вызовах, что и ОС, это не проблема.

Большей проблемой является поддержка времени выполнения. В ОС не так много программных сервисов. Например, обычно нет виртуальной машины Java. (Нет причин, по которым там технически не могло быть, но обычно, но обычно, можно с уверенностью предположить, что он не присутствует).

К сожалению, в своем представлении по умолчанию, как Java байт-код, для Java-программы требуется много инфраструктуры. Ему нужна виртуальная машина Java для интерпретации и JIT байт-кода, и ему нужна библиотека классов и т.д.

Но есть два способа обойти это:

* Поддержка Java в ядре. Это будет необычный шаг, но это можно сделать.
* Или скомпилируйте исходный код Java в собственный формат. Программу Java не нужно компилировать в байт-код Java. Вы можете скомпилировать его для ассемблера x86. То же самое касается любых библиотек классов, которые вы используете. Они тоже могут быть скомпилированы до ассемблера. Конечно, части библиотеки классов Java требуют определенных функций ОС, которые не будут доступны, но тогда использование этих классов можно было бы избежать.

Так что да, это можно сделать. Но это не просто, и непонятно, что вы получили.

Конечно, другая проблема может заключаться в том, что Java не позволит вам получить доступ к произвольным местам памяти, что значительно затруднит передачу аппаратного обеспечения. Но это тоже можно было бы обработать, возможно, вызывая очень простые функции C, которые просто возвращают соответствующие области памяти в качестве массивов для работы Java.

 

 [Запись драйверов устройств Solaris в Java](http://research.sun.com/techrep/2006/abstract-156.html) охватывает устройство A RAM, написанное на Java.

 [Еще один для Linux](https://portal.acm.org/citation.cfm?id=1408654.1408657). Более подробно рассказывается о том, почему вам может понадобиться DD на Java (так как некоторые люди задавались вопросом о других сообщениях и комментариях)

 

Это не невозможно, но, возможно, трудно и, возможно, не имеет большого смысла.

Возможно, потому что Java - это обычный язык программирования, если у вас есть какой-то способ доступа к данным, это не проблема. Обычно в современной ОС ядро имеет слой, позволяющий каким-то образом обеспечить необработанный доступ к оборудованию. Также уже существуют драйверы в пользовательском пространстве, по крайней мере часть userpace-Part не должна быть проблемой для реализации на Java.

Это делает не слишком много смысла, потому что ядро должно запустить JVM для запуска драйвера. Также JVM-реализации обычно содержат много памяти.

Вы также можете использовать Java-код, скомпилированный для выполнения на платформе (а не с помощью JVM). Обычно это не так эффективно, но оно может быть подходящим для драйвера устройства.

Вопрос в том, имеет ли смысл реализовать драйвер в Java? Или заявлено по-другому: на что вы надеетесь, если вы используете Java для реализации драйвера вместо другой альтернативы? Если вы можете ответить на этот вопрос, вы должны найти способ сделать это возможным.

В конце намек на [JNode](http://www.jnode.org/) - проект, который пытается реализовать полную ОС исключительно на основе Java.

 

 **Драйвер устройства может быть много вещей**

  На самом деле я пишу драйверы устройств в java для жизни: **драйверы для промышленных устройств**, таких как весы или взвешивающие устройства, упаковочные машины, сканеры штрих-кода, весовые мосты, принтеры для пакетов и коробок,... **Java здесь действительно хороший выбор.**

  [![Some examples]()](/img/810ea1b87bfce4fbd3b76ac3f91d7b0f.png)

  Промышленные устройства **очень отличаются от ваших домашних/офисных устройств (например, сканеры, принтеры)**. Особенно в сфере производства (например, продуктов питания), компании все чаще выбирают централизованный сервер, на котором выполняется приложение MES (например, разработанное на Java). **Сервер MES должен взаимодействовать с устройствами производственной линии, но также содержит бизнес-логику.** Ява - это язык, который может делать и то, и другое.

  Если ваши домашние/офисные устройства часто встроены в ваш компьютер или подключены с помощью кабеля USB, эти **промышленные устройства обычно используют разъемы Ethernet или RS232.** Так что, по сути, почти каждый язык может сделать эту работу.

  **В этой области пока не так много стандартизации.** Большинство поставщиков предпочитают создавать свои собственные протоколы для своих устройств. Ведь они производители аппаратного обеспечения, а не гении программного обеспечения. Результатом является большое разнообразие протоколов. Некоторые поставщики предпочитают простые текстовые протоколы, но другие предпочитают сложные двоичные протоколы с кодами CRC, кадрированием,... Иногда им нравится укладывать несколько протоколов (например, алгоритм подтверждения связи конкретного поставщика поверх уровня OPC). **Сильный язык ООП имеет здесь много преимуществ.**

 
>   Например, я видел печать Java с постоянной скоростью 100 мс/цикл. Это включает в себя создание уникальной этикетки, отправку ее на принтер, получение подтверждения, печать его на бумаге и нанесение его на продукт с использованием давления воздуха.
> 
> 

  **Таким образом, сила Java:**

 * Это полезно как для бизнес-логики, так и для сложного взаимодействия.
* Он так же надежен в связи с сокетами, как и C.
* Некоторые драйверы могут выиграть от мощности Java OOP.
* Ява достаточно быстрая.

 

Возможно, вы слышали ссылку на [JDDK](http://www.javapos.com/jddk.main.html)?

Запись драйвера устройства на 100% в Java  **невозможна без встроенного кода**, чтобы обеспечить взаимодействие между (1) точками входа и соглашениями о конкретном драйвере для ОС и (2) экземпляром JVM. Экземпляр JVM можно запустить "in-process" (и "in-process" может иметь разные значения в зависимости от ОС и от того, является ли драйвер драйвером режима ядра или пользовательского режима) или как отдельная пользовательская земля процесс, с которым может взаимодействовать тонкий, адаптивный уровень адаптивного драйвера, и на который упомянутый слой адаптации драйвера может разгрузить фактическую работу пользователя.

 

У вас слишком узкий вид драйверов устройств.

Я написал такие драйверы устройств поверх MOST в автомобильном приложении. Более широкое использование может быть драйвером для USB-устройств, если Java когда-либо получает приличную библиотеку USB.

В этих случаях существует общий протокол низкого уровня, который обрабатывается в собственном коде, а драйвер Java обрабатывает специфику устройства (форматы данных, конечные автоматы,...).

 

Это  **возможно**, чтобы скомпилировать java-код для инструкций, связанных с оборудованием (то есть не с JVM-байт-кодом). См. Например [GCJ](https://gcc.gnu.org/java/). С этим в руке вы намного ближе к возможности компиляции драйверов устройств, чем раньше.

Я не знаю, насколько это практично.

 

  **Возможно?**

Да, но только в особых обстоятельствах. Потому что вы можете написать операционную систему в Java и С#, а затем, чтобы иметь возможность писать драйверы устройств для нее. Память, попавшая в эти драйверы и операционные системы, будет существенной.

  **Вероятная?**

Скорее всего. По крайней мере, не в мире Windows или MacOS или даже Linux... По крайней мере, в ближайшее время. Поскольку такие языки, как С# и Java, зависят от CLR и JVM. Способ работы этих языков означает, что они не могут быть эффективно загружены в ring0.

Кроме того, удар производительности будет довольно большим, если в драйверах устройств будут использоваться управляемые языки.

 

Для мотивации, пожалуйста, помните, что существует множество быстрых языков, которые лучше, чем C для программирования; они могут быть не такими быстрыми, как C, но они безопасные языки: если вы допустили ошибку, вы не получите поведения undefined. И "поведение undefined" включает в себя выполнение произвольного кода, предоставляемого некоторым злоумышленником, который форматирует ваш HD.
Многие функциональные языки обычно скомпилированы в собственный код.

Драйверы устройств содержат большинство ошибок в ядре ОС - я знаю, что для Linux (Линус Торвальдс и другие так говорят), и я слышал это для Windows. В то время как для диска или Ethernet-драйвера вам нужна первоклассная производительность, а в то время как в Linux-драйверах сегодня есть узкое место для 10G Ethernet или SSD-дисков, большинству драйверов не требуется такая большая скорость - все компьютеры ждут с той же скоростью.

Вот почему существуют различные проекты, позволяющие писать драйверы, которые запускаются за пределами ядра, даже если это вызывает замедление; когда вы можете это сделать, вы можете использовать любой язык, который вам нужен; вам просто понадобятся привязки Java для используемой библиотеки управления оборудованием - если вы пишете драйвер на C, у вас все равно будет библиотека с привязками C.

Для драйверов в режиме ядра, есть две проблемы, о которых я еще не видел:

* Сбор мусора, и это жесткое требование. Вам нужно написать сборщик мусора в ядре; некоторые алгоритмы GC основаны на виртуальной памяти, и вы не можете их использовать. Кроме того, вам, вероятно, потребуется отсканировать всю память ОС, чтобы найти корни для GC. Наконец, я бы только доверял алгоритму, гарантирующему (мягкому) GC в реальном времени, что сделало бы накладные расходы еще большими.
Читая статью, о которой упоминалось о драйверах Java-устройств поверх Linux, они просто сдаются и требуют, чтобы программисты вручную освобождали память. Они пытаются утверждать, что это не поставит под угрозу безопасность, но я не думаю, что их аргумент убедителен - даже не ясно, понимают ли они, что сборка мусора необходима для безопасного языка.
* Отражение и загрузка классов. Полная реализация Java, даже при использовании собственного кода, должна иметь возможность загружать новый код. Это библиотека, которую вы можете избежать, но если у вас есть интерпретатор или JIT-компилятор в ядре (и нет реальной причины, которая делает его технически невозможным).
* Производительность . Документ о JVM в Linux очень плохой, и их показатели производительности не убедительны - действительно, они тестируют сетевой драйвер USB 1.1, а затем показывают, что производительность не так уж плоха! Однако, учитывая достаточно усилий, можно сделать что-то лучше.

Две последние вещи:

* Я хотел бы упомянуть Singularity, которая представляет собой полную ОС, написанную на языке С#, с просто уровнем абстракции оборудования на родном языке.
* О picoJava, это плохая идея использовать его, если ваша система действительно ограничена памятью, как смарт-карта. Cliff Click уже объяснил, почему: это дает лучшую производительность для написания хорошего JIT, и в наши дни даже смартфоны могут это поддерживать.

 

Драйверы устройств должны быть записаны на языке, который может выполняться в ядре, либо скомпилирован в него, либо загружен как модуль во время выполнения. Обычно это препятствует написанию драйверов устройств на Java, но я полагаю, что вы теоретически могли бы реализовать JVM внутри драйвера устройства и позволить ему выполнять Java-код. Не то, чтобы любой здравомыслящий человек захотел это сделать.

В Linux существует несколько пользовательских (т.е. не ядро) реализаций файловых систем, в которых используется общий слой абстракции (плавкий предохранитель), который позволяет программам пользовательской земли реализовывать вещи, которые обычно выполняются в ядре.

 

Windows Driver Foundation (WDF) - это Microsoft API, который позволяет [Пользователь](https://www.microsoft.com/whdc/driver/wdf/UMDF_intro.mspx) и [Драйверы устройств режима ядрa > , которые должны быть записаны. Это делается сегодня, и теперь оно совместимо с w2k и более поздними версиями (используется, чтобы не иметь w2k в качестве поддерживаемой цели). Нет причин, по которым JNI-звонки не могут быть сделаны, чтобы выполнить некоторую работу в JRE., (предполагая, что JNI по-прежнему является способом вызова Java из C/С++... мои знания датированы на этой арене). Это может быть интересным способом, чтобы алгоритмы высокого уровня непосредственно собирали данные из USB-трубки для чего-то с этим., классный материал!](https://www.microsoft.com/whdc/driver/wdf/KMDF.mspx)

 

Драйверы пользовательского пространства PCIe могут быть записаны на Pure Java. См. [JVerbs](http://www.socc2013.org/home/program/a10-stuedi.pdf "JVerbs") для получения подробной информации о прямом аппаратном доступе на основе памяти в контексте OFED. Это метод, который можно использовать для создания высокопроизводительных систем.

Вы можете проверить шину PCI, чтобы определить области памяти для данного устройства, какие у него есть порты и т.д. Области памяти могут отображаться в процессе JVM.

Конечно, вы несете ответственность за реализацию  **всего**.

Я не сказал легко. Я сказал, что возможно.;)

См. также [Драйверы устройств в пространстве пользователя](http://www.embedded.com/design/operating-systems/4401769/Device-drivers-in-user-space), в котором обсуждается использование структуры UIO для создания драйвера пространства пользователя.

 

Прежде всего, обратите внимание на то, что я не эксперт в драйверах устройств (хотя я сам написал несколько раз в день), а тем более эксперт по Java.

Оставьте тот факт, что написание драйверов устройств на высокоуровневом языке не является хорошей идеей (для производительности и, возможно, по многим другим причинам) в сторону на мгновение, и ответьте на ваш вопрос.

Вы можете писать драйверы устройств практически на любом языке, по крайней мере теоретически.

Однако большинству драйверов устройств необходимо выполнять множество низкоуровневых файлов, таких как обработка прерываний и связь с ОС с использованием API-интерфейсов ОС и системных вызовов, которые, я считаю, вы не можете сделать в Java.

Но если ваше устройство связывается с использованием, скажем, последовательного порта или USB, и если ОС не обязательно должно знать устройство (только ваше приложение будет обращаться к устройству *), вы можете написать драйвер на любом языке, который предоставляет необходимые средства для доступа к устройству.

Так, например, вы, вероятно, не можете записать драйвер карты SCSI на Java, но вы можете написать драйвер для проприетарного устройства управления, USB-лавы, лицензионного ключа и т.д.

* Очевидный вопрос здесь, конечно, заключается в том, что он считается драйвером?