Почему операционные системы делают вещи низкого уровня в C и C ++? Почему не только C ++?

20

На странице Википедии для Windows говорится, что Windows написана на ассемблере для загрузчика и переключателя задач, а C и C ++ для подпрограмм ядра.

IIRC, вы можете вызывать функции C ++ из блока extern "C"'d'. Я могу использовать C для функций ядра, чтобы их могли использовать чистые приложения C (как printfи тому подобное), но если они могут быть просто обернуты в extern "C "блок, то зачем код на C?

Коул Джонсон
источник
10
Вы видели различные "Зачем использовать C, когда есть C ++?" вопросы здесь? Это не обязательно дубликат любого из них, но они связаны между собой.
1
«Вы можете вызывать функции C ++ из внешнего блока« C »d как C ++» Вы имеете в виду, что можете вызывать функции C ...?
Code-Guru
@ Code-Guru нет, потому что единственное различие между экспортированными функциями C и C ++ заключается в оформлении имени, а в C ++ добавление thisпеременной
Коул Джонсон
2
Добавьте исключение в ISR и посмотрите, что произойдет
Джеймс
Еще один вопрос C + C ++.
Мачадо

Ответы:

31

Это в основном по историческим причинам. Некоторые части ядра Windows изначально были написаны на C, потому что в 1983 году, более трех десятилетий назад, когда Windows 1.0 была выпущена, C ++ был выпущен с трудом. Теперь эти C-библиотеки останутся там «навсегда», потому что Microsoft сделала обратную совместимость точкой продажи, а переписывание совместимой с ошибками версии C-частей на C ++ требует огромных усилий без какой-либо эффективной выгоды.

back2dos
источник
+1, я думаю, это самый реалистичный ответ (помимо того факта, что могут быть некоторые разработчики ядра Windows, которые просто не любят C ++ или не доверяют компиляторам C ++ для такого низкоуровневого материала). Посмотрите, например, здесь stackoverflow.com/questions/520068/… , почему ядро ​​Linux написано на C.
Док Браун
@ back2dos - хотя их C-код не будет выброшен, это не значит, что он будет использоваться или не обновляться. Я гарантирую, что есть хотя бы один метод, который делает что-то, что было изначально написано и содержится в библиотеке C, которая была перенесена в библиотеку C ++ в Windows 8
Ramhound
8
Мне трудно поверить, что в любом недавнем выпуске Windows есть код Windows 1.0. Windows ME была последней версией Windows, которая не была основана на кодовой базе Windows NT. И даже это было в значительной степени заменено новым ядром RT (которое, насколько я понимаю, не обещает слишком много в плане обратной совместимости).
TMN
@ TMN: аргумент, скорее всего, тоже правильный - я уверен, что на пути от Win 1.0 до настоящего времени было написано много библиотек на C, которые до сих пор являются частью текущей базы кода Win8, и никто в MS не видит ни одной Благо переписать их на C ++.
Док Браун
1
В любом случае, вряд ли найдется код, который общается с ядром Windows. В основном, только водители. Приложения обычно общаются с Win32 API или, возможно, с POSIX API.
MSalters
24

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

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

И это очень важно во встраиваемом программном обеспечении, где стоимость развертываемой ошибки чрезвычайно высока по сравнению с остальной отраслью (сравните Web, где вы можете немедленно применить исправление для всех пользователей). Не говоря уже о критически важных программах и медицинских материалах.

Были попытки сместить C с его доминирующего места в низкоуровневом программировании с языками, которые даже лучше в этом, например, BitC, но они пока не увенчались успехом.

K.Steff
источник
4
+1 За упоминание критически важного программного обеспечения на чистом C (например, авиационное программное обеспечение). Однако в медицинском программном обеспечении также используется C ++ (вместо формальной проверки используется обширное тестирование, что было бы чрезвычайно сложно в C ++).
Джорджио
1
Также C имеет довольно успешное безопасное подмножество MISRA-C. Есть эквиваленты для C ++, но они не являются отраслевым стандартом де-факто (пока). Тенденция в программировании, критически важном для безопасности, заключается в том, что библиотеки и компиляторы также будут вынуждены использовать безопасное подмножество, такое как MISRA. Переписать MISRA-C ++ совместимую версию всей стандартной библиотеки C ++, скорее всего, будет кошмаром.
2
Руководства @Lundin MISRA не являются безопасным подмножеством - у вас все еще есть необработанные указатели и большинство других функций, которые делают C небезопасным - они в основном сосредоточены на том, чтобы не использовать или документировать поведение, специфичное для реализации.
Пит Киркхам
@PeteKirkham MISRA-C обнаружит все самые классические ошибки указателя и проведет статический анализ. Промышленные стандарты безопасности (IEC 61508 и др.), По-видимому, одобряют MISRA-C в качестве безопасного подмножества C. Не так много других полезных альтернатив для критически важного программного обеспечения, если только вы не выберете SPARK Ada, язык, который мало кто знает, с ограниченным инструментом служба поддержки.
2
Это должно было быть выбрано как лучший ответ, поскольку это правильно. Другие, которые предполагают, что C используется только по историческим причинам, сами по себе истеричны.
Роб
15
  1. Время выполнения C намного меньше.
  2. Перевод C ++ в конструкции более низкого уровня менее прозрачен, чем в C. (См. Ссылки и таблицы v для двух быстрых примеров)
  3. C обычно имеет стабильный ABI. С ++ обычно нет. Это означает, что как минимум интерфейс системного вызова должен быть в стиле C. Кроме того, если вам нужны какие-либо динамические модули, наличие согласованного ABI очень помогает.
wnoise
источник
+1 за (2) и (3). Я не убежден в (1).
Томас Эдинг
7
@Thomas Eding: среда выполнения C ++ состоит из среды выполнения C, а также функций C ++, таких как исключения, RTTI и другой распределитель памяти. YMMV относительно того, считается ли это намного большим. (А потом есть стандартная библиотека ...)
wnoise
Ах, я забыл об исключениях и новых / удаленных пулах. RTTI я никогда не использую, хотя: D
Томас Эдинг
11

Причины не технические. Немного сборки неизбежно, но они не вынуждены использовать случайный C, они хотят . Моя компания использует свое собственное собственное ядро, написанное почти полностью на C ++, но нам не нужно поддерживать интерфейс C с ядром, как большинство других, потому что наше встроенное ядро ​​монолитно скомпилировано с нашими приложениями C ++. Когда у вас есть интерфейс C, часто легче написать код интерфейса на C, даже если его можно использовать extern "C"для написания на C ++.

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

Карл Билефельдт
источник
6

Разработчики ядра часто относятся к тем людям, которые чувствуют себя счастливее, когда из источника сразу видно, что на самом деле делает код.

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

Я думаю, что сила C ++ - это очень мощные инструменты для создания библиотек и фреймворков, которые затем упрощают разработку приложений. Очень часто разработчик приложений на C ++ полностью теряется во внутренних библиотеках, заполненных шаблонами, даже если он очень компетентен в создании приложений с использованием этой библиотеки. А написание правильной библиотеки C ++ - очень сложная задача программирования, и сделано она только для того, чтобы обеспечить отличную среду для разработчиков приложений. Библиотеки C ++ не являются внутренне простыми, они (или могут быть ...) просто мощными, но простыми с точки зрения программистов приложений.

Но API ядра не может быть API C ++, это должен быть API, не зависящий от языка, поэтому большинство приятных вещей в C ++ не могут быть непосредственно использованы в этом интерфейсе. Более того, ядро ​​на самом деле не разделено на «библиотечные» и «прикладные» части, разработанные независимо, при этом больше усилий логически направляется на одну библиотеку, чтобы упростить создание массы приложений.

Кроме того, безопасность и стабильность более важны внутри ядра, а виртуальные методы гораздо более динамичны и, следовательно, намного сложнее изолировать и проверить, чем простые обратные вызовы или другие C-подобные механизмы.

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

Хайд
источник
+1. Как разработчик ядра, мое «практическое правило» заключается в том, что если вы не можете легко оценить «касание строк кэша», то используемый вами язык приносит больше вреда, чем пользы.
Брендан
Пояснение: для ядер вы должны предположить, что процессор тратит большую часть своего времени в пользовательском пространстве, а код ядра используется спорадически (например, когда пользовательское пространство вызывает API ядра или происходит прерывание); Это означает, что вы должны принять «холодный кеш». Для современных ЦП (где ОЗУ медленная относительно скорости ЦП) потери в кеше и TLB обходятся дорого, поэтому (в сочетании с ожиданием «холодного кеша») показатель «касание строк кеша» становится чрезвычайно важным показателем производительности и / или масштабируемости.
Брендан
5

Бьярн Страуструп, в интервью в июле 1999 года :

Ни один из этих языков не был радикально отличен или значительно лучше, чем другие современные языки. Они были, однако, достаточно хороши и бенефициарами удачи и социальных факторов

Дэвид
источник
2
Добро пожаловать, Дэвид. При цитировании или цитировании, это хорошая идея, чтобы предоставить ссылку (добавлено!)
Эндрю
3

C является языком очень низкого уровня, по своему дизайну. Это один шаг от ассемблера; зная набор микросхем, на который вы нацеливаетесь, вы можете, немного зная, вручную «скомпилировать» C в ASM. Этот тип языка, близкого к металлическому, является ключевым для высокого уровня оптимизации (производительности, эффективности памяти и т. Д.). Однако, потому что это так близко к металлу, вы не получаете много бесплатно с этим языком; это процедурный, не объектно-ориентированный язык, и поэтому работа с такими конструкциями требует большого количества стандартного кода для создания и использования многозначных конструкций в памяти.

C ++ - это «лучше на один», добавляя ряд удобных функций, таких как динамическое выделение памяти, распределение встроенных структур, большая библиотека предопределенного кода и т. Д., За счет некоторых потерь в эффективности (все еще гораздо лучше чем управляемые среды выполнения). Для обычного кодера преимущества намного перевешивают недостатки в тех областях кодовой базы, которые не нуждаются в антивещественном управлении распределением памяти и т. Д.

Комбинация двух довольно традиционна; вы используете C для написания наиболее критичных для производительности и областей памяти, эффективно использующих память, с которыми вы можете работать более абстрактно с помощью вызовов методов из кода C ++, которые могут быть более элегантно организованы и спроектированы, чем Uber-Performancemant Uber-oogly оптимизированный код C.

Keiths
источник
2
Что касается эффективности, я повторюсь: (1) Люди из C ++ скажут вам, что это фигня. (2) Я говорю, что не вижу причин, по которым это должно происходить, и хотел бы привести конкретные примеры. Не примеры того, как легко написать менее эффективный код, но примеры того, как быть столь же эффективным, как C, требует чрезмерного уродства.
3
Определить «некрасивый»; Я кодирую на C # для жизни, и всякий раз, когда я вижу примеры кода на C ++ в StackOverflow, я смущаюсь, насколько много сумасшествия считается нормальным в повседневном использовании языка. Когда я программировал на C ++, я часто видел код на C и съежился; типы структуры упаковки вручную, вычисления указателя выполнения для ручных переходов, встроенный ASM ... yuck. Некоторые люди жалуются на потерю низкоуровневых знаний среди программистов на Java / .NET; Я считаю это огромным благом для производительности.
KeithS
1
Вы не ответили на мой вопрос;) Под "уродливым" я подразумеваю "безобразный по меркам гуру C ++". Другими словами, примеры, когда нельзя использовать «современный C ++» и быть таким же эффективным, как C.
2
Это может быть правдой (я, честно говоря, не знаю). Что касается разработки ядра (и нескольких других областей), мы не говорим о средних программистах.
3
Люди забывают, что C -> C ++ - это континуум. Слишком часто эти аргументы сравнивают хороший современный C ++ с C. Вы можете взять C-программу и собрать ее с помощью компилятора C ++ за относительно короткое время, и она будет работать точно так же быстро. Если современная функция C ++ «слишком медленная», не используйте ее. Это может даже включать такие вещи, как iostream. «Слишком медленно» никогда не является хорошим оправданием для использования C над C ++.
Gort the Robot
1

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

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

Мой опыт показывает, что при всех умных особенностях и ОО-чистоте C ++ кодирование на простом C позволяет выполнять работу быстрее и эффективнее.

Джеймс Андерсон
источник
0

Возможно, что части C не очень переносимы для компилятора C ++, который используется для частей C ++. Может быть, код C дружит с компилятором C таким образом, что это нарушает компилятор C ++.

Если у вас есть качественный компилятор C ++, почти нет причин смешивать C и C ++ в проекте. Почти.

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

Kaz
источник
-1

Я думаю, что у вас это задом наперед - extern "C"блок гарантирует, что соглашения о вызовах C используются для всех функций в блоке. Таким образом, вы можете вызывать чистые функции C из C ++, а не функции C ++ из C. Несмотря на это, я полагаю, что причина, по которой люди используют и C, и C ++, заключается в том, что многие низкоуровневые библиотеки написаны с использованием C, и легче использовать то, что уже существует (и, по-видимому, отлажен и оптимизирован), чем писать свои собственные. OTOH, C ++ предлагает много хороших высокоуровневых функций, с которыми люди предпочитают работать, поэтому они используют это для остальных.

TMN
источник
-2

Существуют различные уровни встроенных платформ, использующих C в качестве языка программирования (конечно, вы можете свободно использовать язык ассемблера в любое время)

Для «Уровня» я говорю о внутреннем уровне ресурсов SRAM и ROM для системы.

Эти платформы иногда ограничены в ресурсах (например, некоторые платформы 8051 имеют только 128 байтов пользовательской SRAM).

Бессмысленно поддерживать динамическое выделение памяти с таким небольшим объемом оперативной памяти. (новый / удалить) или даже malloc в C.

Одним из основных улучшений от C до C ++ является объектно-ориентированная парадигма. C ++ подходит для программного обеспечения с большим объемом памяти

но не во встроенных прошивках, которые имеют ограничение по размеру до 32 КБ. (например, в 16-битной плате MCU)

Нет необходимости иметь компилятор C ++, который обычно более сложен, чем компилятор C. (по крайней мере, поставщики SDK не будут делать это).

На самом деле я едва могу найти компилятор C ++ на 32-битной платформе ARM7.

Это просто не стоит сложности

В некоторых 8051 (8 бит): 1MB ROM, 128B RAM

TI MSP430 (16 бит): 32 КБ ПЗУ, 4 КБ ОЗУ

ST Microelectronics ARM 32-разрядное ядро ​​процессора Cortex ™ -M3 (STM32F103T4): 16 или 32 КБ флэш-памяти, 6 или 10 КБ SRAM

ansonchau
источник
2
Это не является чем-то новым для других ответов, уже размещенных здесь.
Мартин Питерс
32-битный компилятор C ++ для ARM? Если вы хотите, вы можете скомпилировать LLVM из исходного кода самостоятельно после нескольких модификаций, чтобы получить компилятор C ++ для iOS.
Коул Джонсон
-4

Я вижу пару возможных причин:

  • C немного более эффективен по сравнению с C ++.
  • Некоторые библиотеки, которые они используют, написаны на C.
  • Они используют некоторые части ядра Linux, которое написано на C.

Отредактировано: как выясняется, третий аргумент неверен (см. Комментарии).

Pijusn
источник
5
(1) Люди на С ++ стали бы отличаться. И объективно я не вижу причин, чтобы это было так. (2) C ++ может просто вызывать код на C (в этом весь смысл обратной совместимости и extern "C").
1
Если MS использует некоторые части ядра Linux, а ядром Linux является GPL, не означает ли это, что Windows также должна быть GPL?
TomJ
1
@ TomJ на самом деле, поэтому они были вынуждены пожертвовать пару тысяч строк для Linux. + Как вы думаете, почему они поддерживают разработку Linux?
Pijusn
2
@Pius Его точка зрения (и он прав AFAIK): если бы код GPL был связан с ядром Windows, все ядро ​​должно было бы быть GPL (при условии, что не существует отдельного соглашения с правообладателями).
@delnan, не уверен насчет деталей. Я не юрист, поэтому я не могу комментировать это. Но пару лет назад был небольшой скандал по этому поводу. Не уверен, но я думаю, что я мог быть сетевым модулем, о котором говорили все сумасшедшие вещи.
Пиюсн
-4

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

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

Minthos
источник
C ++ ожидает динамические библиотеки? А что такое динамическая память?
4
-1 за [stuff] that C++ expects. Почему C ++ использует больше кучи, чем C? Почему C ++ требует больше DLL, чем C? Просто НЕ ПРАВДА
Томас Эдинг
1
Исправление: Вы теряете библиотеки, написанные на C ++. Итак, вернемся к квадрату 1, если вы используете C ++ или C. Зачем ограничивать себя функциональностью C, если вы можете использовать шаблоны, классы, деструкторы, const и все прочие полезные свойства.
Томас Эдинг
6
Какая? Шаблоны, исключения, объекты (включая конструкторы, деструкторы, перегруженные операторы, теперь перемещают конструкцию и - практически? - все остальное) и т. Д. Работают отлично, независимо от того, откуда берется память (стек, статическая память, ваш пользовательский пул или что-то еще) , Стандартные контейнеры по умолчанию используют распределение кучи, но их распределители могут быть настроены, и ребята из ядра все равно пишут свои собственные коллекции и управление памятью. -1
2
К вашему сведению: я удалил свое отрицательное голосование, потому что я не думаю, что ваш ответ сейчас активно вреден, но я также не считаю его особенно полезным или проницательным.