# Языки программирования

# Основная информация

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

# История

В прошлом для разработки ОС использовались многие языки высокого уровня, включая C, Forth, Lisp, C#, C++, Modula-2, Ada, Bliss, Smalltalk и PL/1. Однако не все языки подходят для разработки ОС, и во многих языках, отличных от C, требуется достаточное количество разработки на ассемблере, чтобы обеспечить соответствующую среду выполнения, поддерживающую абстракции языка. Такие языки, как C, Modula-2, Ada, Bliss, PL/M и XPL, были разработаны специально для программирования низкоуровневых систем, как в разработке ОС, так и во встроенных системах, в то время как такие языки, как Forth, включают необходимые низкоуровневые функции, даже если они не были предназначены специально для этой цели.

# Предупреждение

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

# Могу ли я использовать язык ЯЗЫКНЕЙМ?

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

Также перед началом стоит ответить на следующие вопросы:

  • Можете ли вы справиться со структурами данных, имеющими определенное расположение битов и байтов (обязательное, например, для структур MMU и подобных вещей)? Или у вас есть соответствующие инструменты?
  • Можете ли вы взять под контроль выделение/освобождение памяти? Или вы можете, по крайней мере, разделить большой кусок памяти на более мелкие куски, которые другие функции могут использовать прозрачно (необходимо для любого вида управления памятью)? И важное следствие здесь - есть ли у вас какая-то поддержка вашего менеджера памяти на вашем языке?
  • Можете ли вы создать самодостаточную runtime-библиотеку для поддержки функций языка, которые вам понадобятся?
  • Может ли ЯЗЫКНЕЙМ легко взаимодействовать с некоторым ассемблерным кодом (да, у вас будет немного, по крайней мере, в runtime-библиотеке, которую вам придется написать)?
  • Если ЯЗЫКНЕЙМ соответствует другим пунктам и является интерпретируемым языком, можете ли вы вызвать код, поступающий из необработанных байтов данных с помощью ЯЗЫКНЕЙМ, т.е. Перейти по определенному адресу и продолжить выполнение там (это будет обязательно для загрузки и запуска программ)?

Если ответ на какой-либо из этих вопросов окажется "упс, нет, я не могу сделать это с языком ЯЗЫКНЕЙМ", то, скорее всего, ЯЗЫКНЕЙМ не поможет в разработке ОС. Эту конкретную проблему часто обходили путем изменения языка и написания новых компиляторов.

# Разве я не могу написать компилятор для ЯЗЫКНЕЙМ?

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

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

Кроме того, подумайте вот о чем: на каком языке вы будете писать свой компилятор? Assembler неуклюжий, поэтому ваш выбор - C или ваш любимый язык, ЯЗЫКНЕЙМ. Если вы используете последнее, как вы будете самозагружаться? Если вы используете первый, вам нужно будет перенести libc и GCC - вы действительно хотите быть самостоятельным... верно?

# Но я слышал об ОС, написанной на языке ЯЗЫКНЕЙМ, разве она не интерпретируется?

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

Время от времени вы можете слышать об операционных системах, написанных на языках, которые обычно интерпретируются или которые используют какой-либо интерпретатор: JavaOS, Genera (Symbolics Lisp Machine OS), Pilot-OS (система для рабочих станций Xerox Alto и Star, написанная в основном на Smalltalk-80), UCSD Pascal, различные системы Forth и т.д. Большинство из них относятся к одной из трех категорий:

  • Операционная система работает в низкоуровневом интерпретаторе, написанном на ассемблере или на каком-либо системном языке, таком как C, который фактически взаимодействует с оборудованием. По сути, "операционная система" - это просто приложение, работающее поверх другой ОС более низкого уровня. Pilot-OS, UCSD Pascal и некоторые ОС Java работают таким образом, хотя у них также есть некоторые модули, которые также компилируются в машинный код (см. Ниже).
  • Весь или часть кода была скомпилирована в машинный код. Это может включать использование подмножества языка с уменьшенными требованиями к времени выполнения (например, Pre-Scheme (opens new window) или Slang (opens new window) - хотя они до сих пор не использовались для разработки ОС, они демонстрируют такой язык реализации низкого уровня, который можно использовать таким образом).
    • Операционные системы на базе Forth являются частным случаем этого. В то время как Forth обычно описывается как интерпретируемый язык, интерпретаторы поточного кода, используемые многими системами FORTH, работают иначе, чем большинство других интерпретаторов; по сути, интерпретатор проходит через различные "слова" Forth, из которых состоит код, пока не достигнет слов низкого уровня, которые реализованы в ассемблере или скомпилированном коде, что на самом деле выполняется. Кроме того, системы Forth включают специальный ассемблер, который создает код, специально предназначенный для использования интерпретатором; кроме того, часто используемые "слова" могут быть скомпилированы в машинный код по мере необходимости. Наконец, многие встраиваемые системы используют специальное оборудование (см. Ниже) для поддержки языка.
    • Большинство систем Lisp свободно смешивают интерпретируемый и компилируемый код, и почти во всех "серьезных" системах Lisp с конца 1970-х годов Слушатель REPL ("командная строка" для системы Lisp) является не интерпретатором, а скорее системой компиляции и запуска - каждый фрагмент кода, по крайней мере, частично компилируется на лету. Хотя ни одна значительная ОС Lisp не была создана без использования аппаратной поддержки, зависящей от языка (см. Ниже), если бы это было так, она, безусловно, не была бы чисто интерпретируемой системой.
  • Система работала на специализированном оборудовании и микрокод, который действовал как встроенный "интерпретатор" для своего основного языка или для портативного байт-кода, который он обычно использовал. Этот тип системы включает в себя SOAR (Smalltalk на RISC), рекурсивную систему, систему Lillith Modula-2 и Burroughs 6500 (мэйнфрейм, предназначенный для запуска Algol-60 в 1960-х годах). Методы системного программирования для них не могут работать на стандартном оборудовании. Например:
    • Архитектура машины MIT CADR Lisp имела обширный набор инструкций с аппаратной поддержкой для некоторых операций высокого уровня, таких как проверка тегов типов и GC. Он имел помеченную архитектуру, означающую, что часть 36-битного адресного слова была предназначена для информации о типе. Как правило, эти машины имели множество компиляторов, включая один для системного языка Lisp, который был способен использовать преимущества дополнительного набора команд.
    • Одноплатный компьютер Rekursiv имел аппаратную поддержку записываемого набора команд (то есть вы могли динамически добавлять инструкции микрокода) и ассоциативные таблицы отправки памяти для поддержки объектно-ориентированного программирования.