Подтвердить что ты не робот

Почему драйверы и прошивки почти всегда написаны на C или ASM, а не на С++?

Мне просто интересно, почему драйверы и прошивки почти всегда написаны на C или Assembly, а не на С++?

Я слышал, что для этого есть техническая причина.

Кто-нибудь знает это?

Много любви, Луиза

4b9b3361

Ответ 1

Поскольку большую часть времени операционная система (или "библиотека времени выполнения" ) предоставляет функциональность stdlib, требуемую С++.

В C и ASM вы можете создавать простые исполняемые файлы, которые не содержат внешних зависимостей.

Однако, поскольку окна поддерживают stdlib С++, большинство драйверов Windows написаны в (ограниченном подмножестве) С++.

Также, когда прошивка написана ASM, обычно это происходит потому, что либо (A), на которой она выполняется, не имеет компилятора С++, либо (B) существуют ограничения по скорости или размеру.

Обратите внимание, что (B), как правило, не было проблемой с начала 2000-х годов.

Ответ 2

Код в ядре работает в совсем другой среде, чем в пользовательском пространстве. Разделение процесса отсутствует, так что ошибок намного сложнее восстановить; исключения в значительной степени не могут быть и речи. Существуют разные распределители памяти, поэтому может быть труднее получить new и delete для правильной работы в контексте ядра. Существует меньше стандартной доступной библиотеки, что значительно затрудняет использование такого языка, как С++.

Windows позволяет использовать очень ограниченное подмножество для С++ в драйверах ядра; по существу, те вещи, которые могут быть тривиально переведены на C, такие как объявления переменных в местах, кроме начала блоков. Они рекомендуют использовать new и delete и не поддерживают RTTI или большую часть стандартной библиотеки С++.

Mac OS X использует I/O Kit, который является основой, основанной на ограниченном подмножестве С++, хотя, насколько я могу судить более полно, чем это разрешено в Windows. Это, по сути, С++ без исключений и RTTI.

Большинство Unix-подобных операционных систем (Linux, BSD) написаны на C, и я думаю, что никто никогда не видел преимуществ добавления поддержки С++ для ядра, учитывая, что С++ в ядре, как правило, настолько ограничен.

Ответ 3

1) "Потому что это всегда было так", - это на самом деле объясняет больше, чем вы думаете, - учитывая, что API-интерфейсы практически во всех существующих системах первоначально были написаны на основе модели C или ASM, и учитывая, что много предыдущих код существует в C и ASM, часто проще "идти с потоком", чем определять, как использовать С++.

2) Окружающая среда. Чтобы использовать все возможности С++, вам нужна довольно среда выполнения, некоторые из которых просто больно предоставить драйверу. Это проще сделать, если вы ограничите свой набор функций, но, среди прочего, управление памятью может стать очень интересным на С++, если у вас мало кучи. Исключения также очень интересны для рассмотрения в этой среде, как RTTI.

3) "Я не вижу, что он делает". Для любого разумно квалифицированного программиста можно взглянуть на линию C и иметь хорошее представление о том, что происходит на уровне машинного кода для реализации этой линии. Очевидно, что оптимизация несколько меняется, но по большей части вы можете сказать, что происходит. В С++, при заданной перегрузке оператора, конструкторах, деструкторах, исключениях и т.д., Очень сложно понять, что произойдет с данной строкой кода. При написании драйверов устройств это может быть смертельно опасно, потому что вы часто ДОЛЖНЫ знать, будете ли вы взаимодействовать с менеджером памяти, или если строка кода влияет (или зависит от) уровней прерываний или маскировки.

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

Ответ 4

За исключением более широкой поддержки инструментов и аппаратной переносимости, я не думаю, что есть веская причина ограничить себя C больше. Я часто вижу сложный материал с ручной кодировкой, сделанный в C, который более естественно можно сделать на С++:

  • Группирование в "модули" функций (не общего назначения), которые работают только с одной и той же структурой данных (часто называемой "объект" ) → Использовать классы С++.
  • Использование указателя "handle", чтобы функции модуля могли работать с "экземплярами" структур данных → Использовать классы С++.
  • Использование функционально-подобных макросов → шаблоны С++ и встроенные функции
  • Разное поведение во время выполнения в зависимости от идентификатора типа с помощью ручной таблицы vtable ( "дескриптор" ) или отправляется с помощью оператора switch → полиморфизм С++
  • Локальная арифметика указателей ошибок для сортировки/демарширования данных из/в порт связи или использования непереносимых структур → концепция потока С++ (не обязательно std:: iostream)
  • Префикс черта из всего, что позволяет избежать конфликтов имен: пространства имен С++

Ни одна из описанных выше функций С++ не стоит больше, чем написанные вручную C-реализации. Вероятно, я пропустил еще кое-что. Я думаю, что инерция С в этой области больше связана с тем, что в основном используется C.

Конечно, вы не сможете использовать STL свободно (или вообще) в среде с ограничениями, но это не значит, что вы не можете использовать С++ как "лучше C".

Ответ 5

Самая большая причина использования C вместо того, чтобы сказать, что чрезвычайно охраняемая Java заключается в том, что очень легко следить за тем, какая память используется для данной операции. C очень ориентирован на адресацию. Ключевой проблемой при написании кода ядра является отказ от ссылки на память, которая может привести к сбою страницы в неудобный момент.

С++ может использоваться, но только если время выполнения специально предназначено для ссылки только на внутренние таблицы в фиксированной памяти (не подлежит просмотру), когда механизм времени выполнения вызывается неявно, например, используя виртуальную таблицу при вызове виртуальных функций. Эта специальная адаптация не используется "из коробки" большую часть времени.

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

Изменить: удалена ссылка на новые и удаленные вызовы (это было неправильно/вводило в заблуждение); заменена более общей фразой "время работы".

Ответ 6

Причина, по которой используется C, а не С++, НЕ:

  • Поскольку С++ медленнее
  • Или потому, что c-runtime уже присутствует.

Это потому, что С++ использует исключения. Большинство реализаций исключений языка С++ непригодны для использования в коде драйвера, поскольку драйверы вызывают, когда ОС реагирует на аппаратные прерывания. Во время аппаратного прерывания код драйвера НЕ разрешен для использования исключений, поскольку это могло бы/могло вызвать рекурсивные прерывания. Кроме того, пространство стека, доступное для кода, в то время как в контексте прерывания, как правило, очень мало (и не может быть получено из-за правила исключения исключений).

Конечно, вы можете использовать новый (std:: nothrow), но поскольку исключения из С++ теперь ubiqutious, это означает, что вы не можете полагаться на какой-либо код библиотеки, чтобы использовать семантику std:: nothrow.

Это также потому, что С++ отказался от некоторых функций C: - В драйверах важно размещать код. Драйверы устройств должны иметь возможность реагировать на прерывания. Код прерывания ДОЛЖЕН быть помещен в сегменты кода, которые "не постранично" или постоянно отображаются в память, так как, если код находился в выгружаемой памяти, он может быть выгружен при вызове, что приведет к исключению, которое запрещено. В компиляторах C, которые используются для разработки драйверов, есть директивы #pragma, которые могут управлять тем, какой тип функций памяти заканчивается. Поскольку не выгружаемый пул - очень ограниченный ресурс, вы НЕ хотите отмечать весь ваш драйвер как невыгружаемый: С++ генерирует много неявного кода. Например, конструкторы по умолчанию. Невозможно скопировать неявно сгенерированный код С++ для управления его размещением, а так как операторы преобразования автоматически вызываются, нет возможности для проверки кода, чтобы гарантировать отсутствие побочных эффектов при вызове кода.

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

Ответ 7

Комментарии, с которыми я столкнулся, почему магазин использует C для встроенной системы в сравнении с С++:

  • С++ создает код bloat
  • Исключения С++ слишком много номер.
  • Полиморфизм С++ и виртуальные таблицы использовать слишком много памяти или выполнить время.
  • Люди в магазине не знают язык С++.

Единственная действительная причина может быть последней. Я видел программы на языке C, которые включают ООП, объекты функций и виртуальные функции. Он становится очень уродливым очень быстрым и раздувает код.

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

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

Большинство причин против С++ связаны с концепциями дизайна, а не с фактическим языком.

Ответ 8

C очень близок к машинному независимому языку ассемблера. Большинство программ OS-типа находятся на уровне "голого металла". С C код, который вы читаете, является фактическим кодом. С++ может скрывать то, что C не может.

Это только мое мнение, но я потратил много времени в своей жизни, отлаживая драйверы устройств и связанные с ОС вещи. Часто просматривая язык ассемблера. Держите его простым на низком уровне и дайте приложению уровень фантазии.

Ответ 9

Драйверы Windows написаны на С++.
Драйверы Linux записываются в c, потому что ядро ​​написано в c.

Ответ 10

Причина, по которой драйверы и прошивки в основном написаны на C или ASM, не зависит от фактических библиотек времени исполнения. Если бы вы представили этот воображаемый драйвер, написанный на C здесь

#include <stdio.h>

#define OS_VER   5.10
#define DRIVER_VER "1.2.3"

int drivermain(driverstructinfo **dsi){
   if ((*dsi)->version > OS_VER){
       (*dsi)->InitDriver();
       printf("FooBar Driver Loaded\n");
       printf("Version: %s", DRIVER_VER);
       (*dsi)->Dispatch = fooDispatch;
   }else{
       (*dsi)->Exit(0);
   }
}

void fooDispatch(driverstructinfo *dsi){
   printf("Dispatched %d\n", dsi->GetDispatchId());
}

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

Поставить другим способом, с драйвером, этот код драйвера имеет право выполнять код вместе с кодом ядра, который будет использовать одно и то же пространство, ring0 - это конечная привилегия выполнения кода (все инструкции разрешены), ring3 - это то, где передняя часть операционной системы работает (ограниченная привилегия выполнения), другими словами, код ring3 не может иметь команду, зарезервированную для ring0, ядро ​​будет убивать код, улавливая его, как бы говоря: "Эй, у вас нет привилегия, чтобы протестировать домен ring0.

Другая причина, по которой она написана на ассемблере, в основном связана с размером кода и исходной скоростью, это может быть, скажем, драйвер последовательного порта, где вход/выход является "критическим" для функции по отношению к время, латентность, буферизация.

Большинство драйверов устройств (в случае Windows) будут иметь специальную комбинацию компилятора (WinDDK), которая может использовать код C, но имеет не связаны с обычными стандартными библиотеками времени выполнения C.

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

Отладочная сторона сложнее, код ring0 не легко доступен по коду ring3, поскольку двери к нему закрыты, через дверцу ловушки ядра (из-за отсутствия лучшего слова) и, если вежливо спросить, дверь все еще остается закрывается, когда ядро ​​делегирует задачу обработчику, проживающему на ring0, выполняет его, любые результаты возвращаются обратно в код ring3, и дверь все еще остается закрытой. Это аналогичная концепция того, как код userland может выполнять привилегированный код на ring0.

Кроме того, этот привилегированный код может легко портить пространство памяти ядра и повредить что-то, следовательно, панику /bluescreens ядра...

Надеюсь, что это поможет.

Ответ 11

Возможно, потому, что драйвер не требует объектно-ориентированных функций, а факт, что C все еще имеет несколько более зрелые компиляторы, будет иметь значение.

Ответ 12

Вероятно, потому что c все еще часто быстрее, меньше при компиляции и более согласованно в компиляции между различными версиями ОС и с меньшим количеством зависимостей. Кроме того, поскольку С++ действительно построен на c, вопрос в том, что вам нужно то, что он предоставляет?

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

Ответ 13

Существует много типов программирования, таких как процедурные, функциональные, объектно-ориентированные и т.д. Объектно-ориентированное программирование больше подходит для моделирования реального мира.

Я бы использовал объектно-ориентированные драйверы устройств, если он им подходит. Но большую часть времени, когда вы программируете драйверы устройств, вам не нужны преимущества, предоставляемые С++, такие как абстракция, полиморфизм, повторное использование кода и т.д.

Ответ 14

Ну, драйверы IOKit для MacOSX написаны на подмножестве С++ (без исключений, шаблонов, множественного наследования). И есть даже возможность писать Linux-модули ядра в haskell.)

В противном случае C, являющийся переносным языком ассемблера, отлично улавливает архитектуру и вычислительную модель фон Неймана, позволяя прямо контролировать все ее особенности и недостатки (например, "узкое место" фон Неймана). C делает именно то, для чего он был разработан, и полностью улавливает целевую модель абстракции (ну, за исключением неявного предположения в едином потоке управления, который можно было бы обобщить, чтобы покрыть реальность аппаратных потоков), и именно поэтому я считаю, что это красиво язык.) Ограничение выразительной способности языка к таким основам устраняет большинство непредсказуемых деталей трансформации, когда к этому фактическому стандарту применяются различные вычислительные модели. Другими словами, C заставляет вас придерживаться основ и позволяет довольно точно контролировать то, что вы делаете, например, при моделировании общности поведения с виртуальными функциями вы точно контролируете, как таблицы указателей функций сохраняются и используются при сравнении с неявным распределением vtbl С++ и управления. Это действительно полезно при рассмотрении кешей.

Сказав это, объектная парадигма очень полезна для представления физических объектов и их зависимостей. Добавляя наследование, мы получаем объектно-ориентированную парадигму, которая в свою очередь очень полезна для представления иерархии структур и поведения физических объектов. Ничто не мешает кому-либо использовать его и выражать его в C, что позволяет полностью контролировать то, как ваши объекты будут созданы, сохранены, уничтожены и скопированы. На самом деле это подход, применяемый в модели устройства Linux. Они получили "объекты" для представления устройств, иерархию реализации объектов для моделирования зависимостей управления питанием и взломанной функциональности наследования для представления семейств устройств, все сделано на C.

Ответ 15

потому что с системного уровня драйверы должны контролировать каждый бит каждого байта памяти, другой более высокий язык не может этого сделать или не может сделать это изначально, только C/Asm достигает ~