Требуется ли для запуска исполняемого файла ядро ​​ОС?

53

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

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

Я прочитал похожий вопрос . Он не объяснил, является ли машинный код, сгенерированный после компиляции, инструкцией непосредственно для ЦП, или ему потребуется снова пройти через ядро, чтобы создать правильную инструкцию для ЦПУ. Т.е. что происходит после загрузки машинного кода в память? Пройдет ли оно через ядро ​​или напрямую пообщается с процессором?

GRANZER
источник
29
Если вы пишете код для Arduino, вам не нужна ОС.
августа
12
printfне очень хороший пример. Он явно определен спецификацией C как функция, которая доступна только в «размещенных» реализациях (имеется в виду запуск в ядре, в отличие от «автономного», который может не требовать его). И на большинстве платформ printfэто просто функция, предоставляемая вами, libcкоторая делает кучу вещей от вашего имени (которая в конечном итоге включает системный вызов для печати на стандартный вывод). Это на самом деле ничем не отличается от вызова libvlc_media_list_add_mediaили PyObject_GetAttr, за исключением того, что некоторые printfреализации гарантированно связываются без добавления дополнительных нестандартных -ls.
Абарнерт
1
Это существует! (не аффилирован, просто подумал, что это круто) erikyyy.de/invaders
Нонни Мус
9
Это действительно зависит от вашего точного определения терминов «исполняемый файл», «ядро», «запустить», «необходимость», «поговорить с» и «пройти». Без точного определения этих терминов вопрос не подлежит ответу.
Йорг Миттаг
3
@ JörgWMittag - Если вы хотите быть педантичным, то почему вы изучаете только эти термины и только этот вопрос? Действительно важный термин, который нужно определить, это «операционная система», которая сомнительно применяется к MS-DOS (и аналогичным средам выполнения одной задачи). Если есть несколько (дезинформированных) людей, которые думают, что BIOS ПК - это операционная система , то все ли в порядке? Думаю, нет. ОП использует эти слова в контексте, который кажется либо разумным (особенно если он не является носителем английского языка), либо нетехническим.
опилки

Ответы:

86

Как человек, который написал программы, которые выполняются без ОС, я предлагаю однозначный ответ.

Требуется ли для запуска исполняемого файла ядро ​​ОС?

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

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


... выводом компилятора является машинный код (исполняемый файл), который, как я думал, был инструкцией непосредственно для процессора.

Верный.

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

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


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

Каждая инструкция выполняется процессором.
Неподдерживаемая или недопустимая инструкция (например, процесс имеет недостаточные привилегии) ​​вызовет немедленное исключение, и ЦП вместо этого выполнит подпрограмму для обработки этого необычного условия.

Функция printf () не должна использоваться в качестве примера «простого исходного кода» .
Перевод с объектно-ориентированного языка программирования высокого уровня на машинный код может быть не таким тривиальным, как вы предполагаете.
Затем вы выбираете одну из самых сложных функций из библиотеки времени выполнения, которая выполняет преобразование данных и ввод-вывод.

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


... что происходит после загрузки машинного кода в память?

Это зависит от окружающей среды.

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

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

Пройдет ли оно через ядро ​​или напрямую пообщается с процессором?

Машинный код выполняется процессором.
Они не «проходят через ядро» , но и не «общаются с процессором» .
Машинный код (состоящий из кода операции и операндов) является инструкцией для ЦП, которая декодируется, и операция выполняется.

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

опилки
источник
2
«Если вы планируете запускать отдельную программу (то есть без ОС), то вы не должны загружать компьютер для запуска ОС». не совсем правильно. Многие DOS-программы загружались после DOS, а затем полностью игнорировали DOS-сервисы (путем прямого бита или, возможно, прямого вызова BIOS). Win3.x является отличным примером, который (за исключением некоторых интересных случаев) игнорировал присутствие DOS. Win95 / 98 / Me тоже сделал это. Есть много примеров ОС, которые поддерживают отдельные программы, многие из которых были в 8- / 16-битной эпохе.
Эрик Тауэрс
8
@EricTowers - Под "DOS" вы подразумеваете MS-DOS (поскольку я использовал DOS, не связанные с MS или Intel)? Вы цитируете «ОС», которая даже не соответствует критериям моих учебников для колледжей 1970-х годов по понятиям и дизайну ОС. Происхождение MS-DOS восходит (через Seattle Computer Products) к CP / M, который автор Gary Kildall явно не называет ОС. FWIW ОС, которая позволяет программе захватить систему, не справилась с основной функцией управления системными ресурсами. «Есть много примеров ОС, которые поддерживают отдельные программы» - «Поддержка» или неспособность предотвратить?
опилки
5
... или ProDOS, или PC-DOS, или DR-DOS, или CBM DOS, или TRS DOS, или FLEX ...
Эрик Тауэрс
3
Мне нравится "автономная" терминология GCC. Английское слово имеет все правильные значения для кода, который работает без ОС, возможно, даже лучше, чем «автономный». Например, вы можете скомпилировать, gcc -O2 -ffreestanding my_kernel.c special_sauce.Sчтобы сделать исполняемый файл, который не предполагает наличия каких-либо обычных библиотек или ОС. (Конечно, обычно вам понадобится скрипт компоновщика, чтобы он мог с пользой ссылаться на формат файла, который загрузчик захочет загрузить!)
Питер Кордес
4
@PeterCordes «автономный» - это термин, используемый в стандарте C, который IMO можно считать несколько авторитетным. В качестве альтернативы хорошим термином также является «не хостинг» (как в хостинге ОС)
Ян Дорняк
38

Ядро "просто" больше кода. Просто этот код - это слой, который живет между самыми низкими частями вашей системы и реальным оборудованием.

Все это работает непосредственно на процессоре, вы просто переходите через его слои, чтобы что-то делать.

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

Фактический код вашей программы выполняется на процессоре, но ветви, которые код создает для печати чего-либо на экране, проходят через код для printfфункции C , через различные другие системы и интерпретаторы, каждая из которых выполняет свою собственную обработку, чтобы понять, как hello world! на самом деле печатается на вашем экране.

Скажем, у вас есть терминальная программа, работающая в оконном менеджере рабочего стола, работающая на вашем ядре, которая, в свою очередь, работает на вашем оборудовании.

Есть много чего еще, но давайте будем проще ...

  1. В вашей терминальной программе вы запускаете программу для печати hello world!
  2. Терминал видит, что программа записала (через процедуры вывода C) hello world!на консоль
  3. Терминальная программа переходит к диспетчеру окон рабочего стола со словами: «Я hello world!написал на меня, не могли бы вы поставить его на место x, yпожалуйста?»
  4. Диспетчер окон рабочего стола подходит к ядру: «Одна из моих программ хочет, чтобы ваше графическое устройство поместило какой-то текст в эту позицию, доберитесь до этого, чувак!»
  5. Ядро передает запрос драйверу графического устройства, которое форматирует его так, чтобы видеокарта могла его понять.
  6. В зависимости от того, как подключена видеокарта, необходимо вызвать другие драйверы устройств ядра, чтобы вытолкнуть данные на шины физических устройств, таких как PCIe, обрабатывая такие вещи, как проверка выбора правильного устройства и возможность передачи данных через соответствующий мост или преобразователи
  7. Аппаратное обеспечение отображает вещи.

Это огромное упрощение только для описания. Здесь будут драконы.

Эффективно все , что вы делаете , что доступ потребности в оборудовании, будь то отображения, блоки памяти, биты файлов или что - нибудь подобное , что есть , чтобы пройти через какой - то драйвер устройства в ядре работать точно , как разговаривать с соответствующим устройством. Будь то драйвер файловой системы поверх драйвера контроллера жесткого диска SATA, который находится поверх мостового устройства PCIe.

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

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

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

Все это обрабатывается слоями на слоях кода.

Мокубай
источник
Не только аппаратный доступ, большая часть обмена данными между программами также проходит через ядро; то, что обычно не включает ядро, устанавливает более прямой канал. Однако для целей этого вопроса также возможно и на практике практикуется в гораздо более простых случаях объединять весь код в одну программу.
Крис Стрэттон,
Действительно, ваша терминальная программа даже не должна быть запущена на той же машине, что и программа, которая пишет что-то для нее.
jamesqf
Поскольку в этом вопросе, возможно, необходимо четко указать - учтите, что когда мы говорим о программах, «говорящих» друг с другом, это метафорично.
user253751
21

Это зависит от окружающей среды. На многих старых (и более простых!) Компьютерах, таких как IBM 1401, ответом будет «нет». Ваш компилятор и компоновщик выпустили автономный «двоичный файл», который работал без какой-либо операционной системы. Когда ваша программа перестала работать, вы загрузили другую, которая также работала без ОС.

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

Кроме того, современные компьютеры (в отличие, скажем, от 1401) поддерживают подключение самых разных устройств ввода-вывода, а не только тех, которые IBM продавала вам в прежние времена. Ваш компилятор и компоновщик не может знать обо всех возможностях. Например, ваша клавиатура может быть подключена через PS / 2 или USB. ОС позволяет устанавливать специфичные для устройства «драйверы устройств», которые знают, как общаться с этими устройствами, но предоставляют общий интерфейс для класса устройств для ОС. Таким образом, ваша программа и даже ОС не должны делать ничего другого для получения нажатий клавиш с USB на клавиатуру PS / 2 или для доступа, скажем, к локальному диску SATA, к USB-устройству хранения или к хранилищу, находящемуся где-то в другом месте. на NAS или SAN. Эти детали обрабатываются драйверами устройств для различных контроллеров устройств.

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

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

Например, в среде Arduino ОС на самом деле отсутствует. Конечно, есть куча библиотечного кода, который среда сборки включает в каждый «двоичный» файл, который она собирает. Но поскольку этот код не сохраняется из одной программы в другую, это не ОС.

Джейми Ханрахан
источник
10

Я думаю, что многие ответы неправильно понимают вопрос, который сводится к следующему:

Компилятор выводит машинный код. Этот машинный код выполняется непосредственно процессором или он «интерпретируется» ядром?

По сути, процессор непосредственно выполняет машинный код . Было бы значительно медленнее, чтобы ядро ​​выполняло все приложения. Однако есть несколько предостережений.

  1. Когда присутствует ОС, прикладным программам обычно запрещено выполнять определенные инструкции или получать доступ к определенным ресурсам. Например, если приложение выполняет инструкцию, которая изменяет таблицу системных прерываний, ЦП вместо этого перейдет к обработчику исключений ОС, чтобы приложение-нарушитель было завершено. Кроме того, приложениям обычно не разрешается чтение / запись в память устройства. (То есть «общение с оборудованием».) Доступ к этим специальным областям памяти - это то, как ОС взаимодействует с такими устройствами, как графическая карта, сетевой интерфейс, системные часы и т. Д.

  2. Ограничения, накладываемые ОС на приложения, достигаются благодаря специальным функциям ЦП, таким как режимы привилегий, защита памяти и прерывания. Хотя любой процессор, который вы найдете в смартфоне или ПК, имеет эти функции, некоторые процессоры не имеют. Этим ЦП действительно нужны специальные ядра, которые «интерпретируют» код приложения для достижения желаемых функций. Очень интересным примером является Gigatron , компьютер с 8 инструкциями, который вы можете собрать из микросхем, который имитирует компьютер с 34 командами.

  3. Некоторые языки, такие как Java, «компилируются» в нечто, называемое байт-кодом, которое на самом деле не является машинным кодом. Хотя в прошлом они интерпретировались для запуска программ, в наши дни обычно используется то, что называется компиляцией Just-in-Time, поэтому они в конечном итоге запускаются непосредственно на CPU как машинный код.

  4. Запуск программного обеспечения на виртуальной машине раньше требовал, чтобы ее машинный код был «интерпретирован» программой, называемой гипервизором . Из-за огромного промышленного спроса на виртуальные машины производители процессоров добавили функции, такие как VTx, в свои процессоры, чтобы позволить большинству команд гостевой системы выполняться непосредственно процессором. Однако при запуске программного обеспечения, разработанного для несовместимого ЦП на виртуальной машине (например, эмуляция NES), машинный код необходимо будет интерпретировать.

Artelius
источник
1
Хотя байт-код Java обычно не является машинным кодом, все же существуют процессоры Java .
Руслан
Гипервизоры никогда не были переводчиками. Интерпретация, конечно, необходима, если виртуальная машина как набор команд несовместима с ее хостом, но для выполнения с той же архитектурой даже ранние гипервизоры выполняют код непосредственно на ЦП (вы можете быть смущены необходимостью паравиртуализированных ядер для ЦП без необходимая поддержка гипервизора).
Тоби Спейт
5

Когда вы компилируете свой код, вы создаете так называемый «объектный» код, который (в большинстве случаев) зависит от системных библиотек ( printfнапример), затем ваш код оборачивается компоновщиком, который добавит загрузчик программ, который может использовать ваша конкретная операционная система. распознавать (именно поэтому вы не можете запустить программу, скомпилированную для Windows на Linux, например) и знать, как развернуть код и выполнить. Таким образом, ваша программа в виде мяса внутри бутерброда и может быть съедена только в комплекте.

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

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

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

Ну, ядро ​​как официантка, чья обязанность подвести вас к столу и служить вам. Единственное, что он не может сделать - это есть для вас, вы должны сделать это сами. То же самое с вашим кодом, ядро ​​распакует вашу программу в память и запустит ваш код, который является машинным кодом, выполняемым непосредственно процессором. Ядро просто должно контролировать вас - что вам разрешено и что вам нельзя делать.

это не объясняет, является ли машинный код, который генерируется после компиляции, инструкцией непосредственно для ЦП, или ему нужно будет снова пройти через ядро, чтобы создать правильную инструкцию для ЦП?

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

Что происходит после загрузки машинного кода в память? Пройдет ли оно через ядро ​​или напрямую пообщается с процессором.

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

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

Alex
источник
3

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

По сути, только системные вызовы идут в ядро. Все, что связано с вводом-выводом или выделением / освобождением памяти, обычно в конечном итоге приводит к системному вызову. Некоторые инструкции могут быть выполнены только в режиме ядра и вызовут исключение ЦП. Исключения вызывают переход в режим ядра и переход к коду ядра.

Ядро не обрабатывает каждую инструкцию в программе. Он просто выполняет системные вызовы и переключается между запущенными программами для совместного использования процессора.

Распределение памяти в пользовательском режиме (без ядра) невозможно, если вы обращаетесь к памяти, к которой у вас нет прав доступа, MMU, ранее запрограммированный ядром, замечает и вызывает исключение «ошибка сегментации» на уровне процессора , который запускает ядро, а ядро ​​убивает программу.

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


Требуется ли для запуска исполняемого файла ядро ​​ОС?

Зависит от типа исполняемого файла.

Ядра, помимо обеспечения совместного доступа к ОЗУ и аппаратному обеспечению, также выполняют функцию загрузчика.

Многие "исполняемые форматы", такие как ELF или PE, содержат метаданные в исполняемом файле в дополнение к коду, и его работа по загрузке - обрабатывать это. Прочитайте кровавые подробности о формате Microsoft PE для получения дополнительной информации.

Эти исполняемые файлы также ссылаются на библиотеки ( .dllобщие объектные .soфайлы Windows или Linux ) - их код должен быть включен.

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

  • Можете ли вы включить код, который выполняет работу загрузчика?

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

  • Что если он не вызывает API ядра?

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

  • Что делать, если вы запускаете его из режима ядра.

Тогда это будет работать.


LawrenceC
источник
Это не совсем правильно. Требование, чтобы аппаратный доступ проходил через ядро ​​или даже было ядро, является конструктивным решением, принятым утвердительно на многих системах сегодня, но также и отрицательным (даже по сей день) на многих простых системах.
Крис Страттон
Я объясняю, как обстоят дела, если A) есть ядро ​​и B) если вы выполняете код на ЦП в режиме пользователя / супервизора и MMU, чтобы помочь обеспечить это. Да, существуют процессоры и микроконтроллеры без MMU или режима пользователя / супервизора, и да, некоторые системы работают без использования всей инфраструктуры пользователя / супервизора. Первый Xbox от Microsoft был таким - хотя стандартный процессор x86 с режимом пользователя / супервизора, насколько я понимаю, никогда не выходил из режима ядра, - загруженная игра могла делать все, что хотела.
Лоуренс,
1
Система Macintosh, до MacOS X, была операционной системой компьютера общего назначения , работавшего на ЦП общего назначения (семейство 68000, PowerPC) с поддержкой защиты памяти в течение десятилетий (за исключением первых компьютеров на базе 68000, я думаю), которые никогда не использовали защиту памяти : любая программа может получить доступ ко всему в памяти.
любопытный парень
3

TL; DR No.

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

Аналогично, игры для Sega Genesis не имели ОС, предоставляемой Sega для вызова. Вы только что создали свою игру на ассемблере 68K, написав прямо на голое железо.

Или там, где я порезался, выполняя встроенную работу на Intel 8051. Опять же, когда у вас есть только 2716 eprom с размером 2k * 8, у вас нет места для операционной системы.

Конечно, это предполагает очень широкое использование слова приложения. В качестве риторического вопроса стоит спросить себя, действительно ли эскиз Arduino является приложением.

dgnuff
источник
3

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

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

Ваша путаница проистекает из использования слова «оборудование». Хотя это разделение не такое четкое, как раньше, лучше подумать о периферии, а не просто называть все аппаратным. Таким образом, если на вашем компьютере установлена ​​операционная система или аналогичная, ваша программа должна использовать свои службы для доступа к периферийным устройствам, но сам процессор не является периферийным устройством, это основной процессор, на котором ваша программа работает напрямую.

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

Габор
источник
2

BIOS, который запускается на вашем компьютере при включении, представляет собой исполняемый код, хранящийся в ПЗУ. Он состоит из машинных инструкций плюс данные. Существует компилятор (или ассемблер), который собирает этот BIOS из исходного кода. Это особый случай.

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

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

На другом конце спектра находится Java. В Java компилятор не переводит исходный код в машинные инструкции, как обычно понимают этот термин. Вместо этого исходный код переводится в «машинные инструкции» для воображаемой машины, называемой виртуальной машиной Java. Перед запуском Java-программы ее необходимо объединить со средой выполнения Java, которая включает в себя интерпретатор для виртуальной машины Java.

Уолтер Митти
источник
2

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

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

Все это привело к перемещению большого количества вспомогательного кода из отдельных программ в «операционную систему» ​​со стандартизованным способом вызова вспомогательного кода из пользовательских программ.

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

Были написаны микроядра, которые предоставляют именно то, что нужно для запуска конкретной программы без полноценной операционной системы. Это имеет некоторые преимущества для опытных пользователей, отдавая большинство других. Вы можете прочитать об этом на странице Википедии - https://en.wikipedia.org/wiki/Microkernel - если хотите узнать больше.

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

Турбьерн Равн Андерсен
источник
1

В типичных настольных операционных систем, ядро само по себе является исполняемым. (Windows имеет ntoskrnl.exe; Linux имеет vmlinuxи т. Д.) Если для запуска исполняемого файла вам нужно ядро, то эти ОС не могут существовать.

Для чего вам нужно ядро ​​- это делать то, что делает ядро. Разрешить одновременное выполнение нескольких исполняемых файлов, рефери между ними, абстрагирование аппаратного обеспечения и т. Д. Большинство программ не в состоянии сделать это самостоятельно, и вы не захотите их, даже если бы могли. Во времена DOS, которую едва можно было назвать самой операционной системой, игры часто использовали ОС лишь как загрузчик и обращались к оборудованию напрямую, как ядро. Но вам часто приходилось знать, какие марки и модели оборудования были на вашей машине, прежде чем вы купили игру. Многие игры поддерживают только определенные семейства видео и звуковых карт, и очень плохо работают на конкурирующих брендах, если они вообще работают. Это'

Chao
источник