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

Как выполняется программа? Где действуют операционные системы?

Программа скомпилирована с некоторого языка на ASM → Машинный код (непосредственно исполняемый файл). Когда люди говорят, что это зависит от платформы, значит, что созданные двоичные файлы будут выполняться (правильно) только на процессорах с такой же архитектурой набора инструкций, как x86, x86-64. Он может (неправильно)/не может (вообще) работать на других процессах из-за разницы в ISA. Правильно?

Теперь понятие двоичных файлов меня сбивает с толку. Все дело в "Кодексе машинного языка" и "ЦП". Где ОС вступает в игру? Я имею в виду, что скомпилированный двоичный файл имеет прямые инструкции для CPU, когда он загружается в память. и процессор выполняет одну команду за раз. Я не мог видеть роль операционной системы в любом месте, кроме как в управлении процессом текст ссылки. Он должен работать на ЦПУ той же ISA независимо от операционной системы. правильно?

Но это не так. Если я создам код для x86 на машине Windows. Он не будет работать на машине Mac x86 или Linux x86.

Мне что-то не хватает. Пожалуйста, очистите мое замешательство.

4b9b3361

Ответ 1

Для начала современный процессор имеет (по крайней мере) два режима, режим, в котором он запускает ядро ​​самой операционной системы ( "режим ядра" ) и режим, в котором он запускает программы ( "пользовательский режим" ), В режиме пользователя CPU не может делать много чего.

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

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

Когда в режиме ядра необходимо запустить новый процесс, он сначала выделяет память для бухгалтерии, а затем переходит к загрузке программы. Это включает в себя извлечение инструкций из двоичного файла, а также подключение программы к ОС. Обычно это требует поиска точки входа (классически int main(int argc, char** argv)) двоичного кода и всех точек, где программа хочет вызвать ОС.

Различные операционные системы используют разные способы подключения программ к ОС. В результате процесс загрузки отличается, и форматы файлов для двоичных файлов могут также отличаться. Это не абсолютное; формат ELF для двоичных файлов используется для ряда операционных систем, а Microsoft использует свой формат PE во всех своих текущих операционных системах. В обоих случаях формат описывает точный формат двоичного файла, поэтому ОС может решить, можно ли подключить программу к ОС. Например, если это двоичный файл Win32, он будет в формате PE, поэтому Linux не будет загружать это, Windows 2000 будет, как и Windows 7-64. С другой стороны, двоичный файл Win64 также находится в формате PE, но Windows 2000 отвергает его.

Ответ 2

Он не будет работать на других процессорах, поскольку 01010110011 означает что-то на x86 и что-то еще на ARM. x86-64 оказывается обратно совместимым с x86, поэтому он может запускать программы x86.

Двоичный файл находится в определенном формате, который понимает ваша ОС (windows = PE, mac/linux = ELF)

С любым нормальным двоичным кодом ваша ОС загружает его в память и заполняет несколько полей определенными значениями. Эти "определенные значения" являются адресами для функций api, которые существуют в общих библиотеках (dll, so), таких как kernel32 или libc. Адреса API необходимы, поскольку сам двоичный файл не знает, как получить доступ к жестким дискам, сетевым картам, геймпадам и т.д. Программа использует эти адреса для вызова определенных функций, существующих в вашей ОС или в других библиотеках.

В сущности, в двоичном коде отсутствуют некоторые важные части, которые необходимо заполнить ОС, чтобы все работало. Если ОС заполняет неправильные части, двоичный файл не будет работать, поскольку они не могут общаться друг с другом. Что произойдет, если вы замените файл user32.dll другим файлом или попытаетесь запустить исполняемый файл linux на mac osx.

Итак, как libc знает, как открыть файл?

libc использует syscalls, что является низкоуровневым доступом к основным функциям ОС. Это похоже на вызов функции, за исключением того, что вы делаете это, заполняя некоторые регистры процессора, а затем запуская прерывание (специальная инструкция CPU)

Так как же ОС знает, как открывать файлы?

Это одна из вещей, которую делает ОС. Но как он знает, как разговаривать с жестким диском? Я не знаю точно, как работает этот материал, но я полагаю, что ОС делает это, записывая/считывая определенные ячейки памяти, которые отображаются в функции BIOS.

Итак, как BIOS знает, как разговаривать с жестким диском?

Я тоже этого не знаю, я никогда не программировал на этом уровне. Я полагаю, что BIOS жестко подключен к разъемам жесткого диска и способен отправить правильную последовательность 1 и 0, чтобы поговорить "SATA" с жестким диском. Вероятно, он может просто сказать простые вещи, такие как "читать этот сектор"

Итак, как жесткий диск знает, как читать сектор?

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

Ответ 3

Два способа:

Прежде всего, ответ - "системные вызовы". Всякий раз, когда вы вызываете функцию, которая должна выполнять любые операции ввода-вывода, взаимодействовать с устройствами, выделять память, процессы вилки и т.д., Эта функция должна выполнять "системный вызов". Хотя сама команда syscall является частью X86, доступные системные вызовы и параметры для них зависят от ОС.

Даже если ваша программа не делает никаких системных вызовов (что я не уверен, возможно, и, конечно, не очень полезно), форматы, которые обтекают машинный код, различны для разных ОС. Таким образом, форматы файлов exe (PE) и исполняемого файла linux (обычно ELF) различны, поэтому exe файл не будет выполняться в Linux.

EDIT: это детали низкого уровня. Ответ на более высокий уровень заключается в том, что все, что нужно для доступа к файлам, консоли/графическому интерфейсу, распределению памяти и т.д., Зависит от ОС.

Ответ 4

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

В GNU/Linux, например, вы должны заполнить регистры и вызвать int 80h для доступа к "службе" (фактически называемой "syscall" ).

Ваша программа не будет работать в другой ОС также потому, что для исполняемых файлов существуют разные форматы файлов, например Win имеет COFF/PE, Linux имеет формат файла ELF (как и любой другой формат файла, это также содержит "метаданные" ", например формат файла HTML (или SGML)).

Ответ 5

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

Ответ 6

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

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

Формат файла будет определять необходимые функции и данные, необходимые для работы с вашей системой, а также для запуска процесса в требуемом состоянии. Если вы знакомы с разработкой для C/С++ под Windows, концепция подсистемы определяет уровень начальной загрузки, предоставленные ресурсы и подпись точки входа (обычно main(int, char **) для большинства систем).

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

Языки ассемблера должны кодироваться для конкретной ISA. Они используют инструкции, характерные для семейства типов процессоров. Эти инструкции могут работать в других семействах процессоров, , если, эти ЦП поддерживают данный набор команд. Например, код x86 будет работать в определенной степени, в операционной системе amd64 и определенно работать на процессоре amd64 с операционной системой x86.

C абстрагирует большую часть специфики ISA. Несколько очевидных исключений включают в себя размеры указателя и контенту. Различные известные интерфейсы будут предоставлены ожидаемому уровню через libc, например printf, main, fopen и другие. К ним относятся ожидаемые регистры и состояния стека для выполнения этих вызовов, позволяя C-коду работать в разных операционных системах и архитектурах без изменений. Другие интерфейсы могут быть предоставлены либо напрямую, либо путем привязки платформы к ожидаемому интерфейсу, чтобы увеличить переносимость кода C.

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

Ответ 7

ОС предоставляет инструменты и API для доступа к определенным функциям и аппаратным средствам.

Например, чтобы создать окно в Microsoft Windows, для создания окна вам понадобится ОС DLL.

Если вы не хотите самостоятельно писать API, вы будете использовать API, который предоставляет ОС. Это, когда ОС вступает в игру.

Ответ 8

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

Ответ 9

Аналогия:

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

Теперь предположим, что вы хотите, чтобы он шел от А до Б. Ты не стал бы говорить прямо с его ногами или ногами, ты бы спросил его на его лице! Он контролирует свое тело. Если 1) вы правильно передаете свой запрос и 2) он решает, что он подпадает под его служебные обязанности, он переместится с A на B.

Теперь вы получаете нового слугу из той же страны, что и последняя (потому что вы предпочитаете не покупать новый трансляционный транслятор). Вы хотите, чтобы он тоже шел от А до Б. Но этот слуга требует, чтобы вы говорили громче и говорите, пожалуйста, спрашивая. Вы мириться с этим, потому что он более гибкий: вы можете попросить его перейти от A к B через C, если хотите - предыдущий дворецкий мог это сделать, но тащил ноги и жаловался.

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

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