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

8490
GRANZER

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

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

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

52
Если вы пишете код для Arduino, вам не нужна ОС. stib 5 лет назад 29
`printf` не очень хороший пример. Он явно определен спецификацией C как функция, которая доступна только в «размещенных» реализациях (имеется в виду запуск на ядре, в отличие от «автономного», который может не требовать его). И на большинстве платформ `printf` - это просто функция, предоставляемая вашим` libc`, которая делает кучу вещей от вашего имени (которая в конечном итоге включает системный вызов для печати в stdout). Это на самом деле ничем не отличается от вызова `libvlc_media_list_add_media` или` PyObject_GetAttr`, за исключением того, что некоторая реализация `printf` гарантированно связывается без добавления дополнительных нестандартных` -l`s. abarnert 5 лет назад 12
Это существует! (не связан, просто думал, что это круто) http://www.erikyyy.de/invaders/ Nonny Moose 5 лет назад 1
Это действительно зависит от вашего точного определения терминов «исполняемый файл», «ядро», «запустить», «необходимость», «поговорить с» и «пройти». Без точного определения этих терминов вопрос не подлежит ответу. Jörg W Mittag 5 лет назад 9
@ JörgWMittag - Если вы хотите быть педантичным, то почему вы изучаете только эти термины и только этот вопрос? Действительно важный термин, который нужно определить, это «операционная система», которая сомнительно применяется к MS-DOS (и аналогичным средам выполнения одной задачи). Если есть несколько (дезинформированных) людей, которые думают, что [BIOS компьютера - это операционная система] (https://superuser.com/questions/424892/is-bios-considered-an-os), то все ли в порядке? Думаю, нет. ОП использует эти слова в контексте, который кажется разумным (особенно если он не является носителем английского языка) или нетехническим. sawdust 5 лет назад 3
«с помощью только функции` printf () `" - вы недооцениваете, сколько именно скрыто за "вызовом функции, которая выводит". Вероятно, он доступен через ссылки на библиотеку - а библиотека ABI и ссылки - это то, что ОС определяет и делает при загрузке исполняемого файла - и для ее реализации реализация стандартной библиотеки C может использовать системные вызовы, которые просят ядро ​​ОС записать данные к устройствам. millimoose 5 лет назад 0
Или, конечно, ничего этого не должно произойти, потому что реализация стандартной библиотеки C для встроенного устройства может включать код, который непосредственно выполняет последнюю часть, и компилятор для встроенной системы будет связывать все статически, так что на самом деле это просто поток инструкций, которые непосредственно выполняются на процессоре. Но это особый случай для оборудования, которое обычно запускается без операционной системы, и вам нужен набор инструментов, предназначенный для этого. millimoose 5 лет назад 1
Если бы вы спросили об этом в ретро вычислительном стеке, вы бы получили много ответов о том, как мы использовали компьютеры, прежде чем стали распространяться жесткие диски. Многие (большинство?) Программ запускались без ОС. Вы вставили диск с программой, затем включили компьютер, который загрузился прямо в саму программу. Не было выхода из ОС. Когда вы закончили, вы выключили компьютер. Или вы можете поменять диски и вручную отправить прерывание IPL (начальная загрузка программы), которое на компьютерах IBM и совместимых компьютерах выполнялось с помощью CTRL-ALT-DEL. Это приведет к перезагрузке системы и загрузке нового диска. Todd Wilcox 5 лет назад 1

11 ответов на вопрос

85
sawdust

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

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

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

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


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

Правильный.

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

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


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

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

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

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


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

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

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

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

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

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

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

«Если вы ожидаете запуска автономной программы (то есть без ОС), то вы не должны загружать компьютер для запуска ОС». не совсем правильно. Многие DOS-программы загружались после DOS, а затем полностью игнорировали DOS-сервисы (путем прямого бита или, возможно, вызова BIOS напрямую). Win3.x является отличным примером, который (за исключением некоторых интересных случаев) игнорировал присутствие DOS. Win95 / 98 / Me тоже сделал это. Есть много примеров ОС, которые поддерживают автономные программы, многие из которых относятся к 8- / 16-битной эпохе. Eric Towers 5 лет назад 2
@EricTowers - Под * "DOS" * вы, вероятно, подразумеваете MS-DOS (поскольку я использовал DOS, не связанные с MS или Intel)? Вы цитируете «ОС», которая даже не соответствует критериям моих учебников для колледжей 1970-х годов по понятиям и дизайну ОС. Происхождение MS-DOS восходит (через Seattle Computer Products) к CP / M, который автор Gary Kildall явно не называет ОС. FWIW ОС, которая позволяет программе захватить систему, не справилась с основной функцией управления системными ресурсами. * "Есть много примеров ОС, которые поддерживают автономные программы" * - * "Поддержка" * или не в состоянии предотвратить? sawdust 5 лет назад 8
... или [ProDOS] (https://en.wikipedia.org/wiki/Apple_ProDOS) или [PC-DOS] (https://en.wikipedia.org/wiki/IBM_PC_DOS) или [DR-DOS] ( https://en.wikipedia.org/wiki/DR-DOS) или [CBM DOS] (https://en.wikipedia.org/wiki/Commodore_DOS) или [TRS DOS] (https: //en.wikipedia. org / wiki / TRSDOS) или [FLEX] (https://en.wikipedia.org/wiki/FLEX_ (operating_system)) ... Eric Towers 5 лет назад 5
Мне нравится "автономная" терминология GCC. Английское слово имеет все правильные значения для кода, который работает без ОС, возможно, даже лучше, чем «автономный». Например, вы можете скомпилировать `gcc -O2 -ffreestanding my_kernel.c special_sauce.S`, чтобы создать исполняемый файл, который не предполагает, что там будут какие-либо обычные библиотеки или другие компоненты ОС. (Конечно, обычно вам понадобится скрипт компоновщика, чтобы он мог с пользой ссылаться на формат файла, который загрузчик захочет загрузить!) Peter Cordes 5 лет назад 3
@EricTowers - Зачем перечислять архаичные среды выполнения с одной задачей, когда каждая ОС, не использующая MMU (например, uClinux или «Linux без MMU»), не может защитить систему от мошеннической программы? Но ОП явно имеет в виду безопасную ОС, которая использует защищенные режимы ЦП и MMU, так что ваше отступление педантично. sawdust 5 лет назад 1
@PeterCordes - это интересная информация о GCC, но я не разделяю ваш энтузиазм по поводу этой терминологии. Так как значение слова включает в себя то, что оно не подразумевает, рассмотрим антонимы каждого слова, [этот список] (https://www.powerthesaurus.org/freestanding/antonyms) и [этот список] (https: // www .powerthesaurus.org / автономный / антонимов). (Что является или не является) «автономным» прилагательным / существительным кажется гораздо более кратким, чем «автономным». sawdust 5 лет назад 0
Я нахожу, что «автономный исполняемый файл» звучит так, как будто он может применяться к чему-то, что не зависит от библиотек или других программ (например, статический двоичный файл или просто помещение функции более крупной программы в сам исполняемый файл). Это не обязательно означает, что он не полагается на системные вызовы ОС, если только об этом не говорит окружающий контекст или определение. Я думаю, что отдельно стоящие могут иметь такую ​​же проблему, хотя. Я не утверждаю, что «автономный» является более правильным или широко используемым, но мне это нравится. Это менее распространенное слово, поэтому оно не имеет такого большого количества применений в вычислительной технике. Каждому свое! Peter Cordes 5 лет назад 1
@sawdust: я не уверен, что действительно справедливо судить о выборе слова по какой-то дурацкой записи в тезаурусе? «Отдельно стоящий» и «на фоне» не являются антонимами в каком-либо значимом смысле (это даже не та же часть речи), и аналогично для многих других записей на этой странице. psmears 5 лет назад 2
@PeterCordes «автономный» - это термин, используемый в стандарте C, который IMO можно считать несколько авторитетным. В качестве альтернативы хороший термин также «не размещен» (как в размещении в ОС) Jan Dorniak 5 лет назад 4
Я не уверен, я думаю, что большая часть этого зависит от того, как вы определяете `OS`. Например, если вы пишете загрузчик, это просто программа или вы пишете саму ОС? В конце концов, даже BIOS - это программа, но фактически она сама по себе является операционной системой. ChatterOne 5 лет назад 0
38
Mokubai

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

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

Ваша программа «нуждается» в ядре точно так же, как ей нужны стандартные библиотеки 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.

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

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

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

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

Не только * аппаратный * доступ, большинство сообщений * между * программами также проходит через ядро; то, что обычно не включает ядро, устанавливает более прямой канал. Однако для целей этого вопроса также возможно и практикуется в гораздо более простых случаях объединять весь код в одну программу. Chris Stratton 5 лет назад 0
Действительно, ваша терминальная программа даже не должна быть запущена на той же машине, что и программа, которая пишет что-то для нее. jamesqf 5 лет назад 0
Поскольку в этом вопросе, возможно, необходимо четко указать - учтите, что когда мы говорим о программах, «говорящих» друг с другом, это метафорично. user20574 5 лет назад 0
21
Jamie Hanrahan

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

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

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

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

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

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

10
Artelius

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

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

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

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

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

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

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

Хотя байт-код Java обычно не является машинным кодом, он все еще существует [процессоры Java] (https://en.wikipedia.org/wiki/Java_processor). Ruslan 5 лет назад 1
Гипервизоры никогда не были переводчиками. Интерпретация, конечно, необходима, если виртуальная машина как набор инструкций несовместима с ее хостом, но для выполнения с той же архитектурой даже ранние гипервизоры выполняют код непосредственно на ЦП (вы можете быть смущены необходимостью паравиртуализированных ядер для ЦП без необходимая поддержка гипервизора). Toby Speight 5 лет назад 0
5
Alex

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

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

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

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

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

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

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

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

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

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

3
LawrenceC

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

TL; DR No.

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

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

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

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

3
Gábor

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

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

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

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

2
Walter Mitty

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

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

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

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

2
Thorbjørn Ravn Andersen

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

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

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

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

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

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