понимание необходимости компиляторов для разных платформ - PullRequest
5 голосов
/ 10 ноября 2010

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

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

РЕДАКТИРОВАТЬ: Большинство ответов до сих пор о вызове APIs ОС .Это, очевидно, проблема.Мой вопрос о прямом машинном коде .Это передается прямо в процессор или нет?Если бы я написал программу на ассемблере, нужно ли мне компилировать отдельно для каждой ОС?(примечание: если я использовал стандартный c ++ cin / cout, зависит ли это от ОС, компилируется ли для ввода-вывода с прямой сборкой или ответ зависит от компилятора?)

Ответы [ 7 ]

8 голосов
/ 10 ноября 2010

Все сводится к API операционной системы и ABI .

Различные операционные системы предоставляют различные системные вызовы , а также разные механизмы для вызова этих системных вызовов. Например, в то время как POSIX предоставляет fork и execv для создания нового процесса, Windows предоставляет CreateProcess.

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

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

8 голосов
/ 10 ноября 2010

Различные операционные системы поддерживают разные двоичные форматы (например, ELF против COFF), разные динамические компоновщики (с файлами * .so, * .dll и * .dylib, связанными во время выполнения, после того, как вы распространили свой двоичный файл), и предоставляет различные наборы функций и библиотек для использования предоставляемых ОС функций.

К различным наборам функций можно обратиться, например, с помощью спецификации Single UNIX / IEEE Std. 1003.1 (POSIX), который предписывает единый набор функций, которые должны быть предоставлены во всех операционных системах для различных задач операционной системы (к сожалению, не все ОС - хм, Windows - соответствуют). Что касается двоичных форматов (а также архитектуры набора команд ЦП), один из способов справиться с этим - распространить некоторый двоичный формат более высокого уровня (байт-код), а затем выполнить преобразование «точно в срок» в целевой набор команд и двоичный формат (хотя это больше об изменении, когда вы делаете это ... это все еще нужно сделать). Например, низкоуровневая виртуальная машина (LLVM) обеспечивает такое преобразование.

6 голосов
/ 10 ноября 2010

Потому что, с одной стороны, возможность взаимодействия с операционной системой не совместима между платформами. Даже между Linux / x86, Windows и Mac / Intel (которые все могут использовать один и тот же процессор) способ действий может сильно отличаться.

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

Одним из примеров является распределение памяти. Если вы хотите запросить больше памяти у ОС под UNIX, вы можете использовать библиотечную функцию brk или sbrk. Это не часть стандартной библиотеки C, более специфичная для UNIX.

С другой стороны, Windows может предоставить функцию Win32GetMem для того же.

1 голос
/ 10 ноября 2010

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

Так что проблема не в самом компиляторе, а в наборе стандартных библиотек, которыекаждая ОС позволяет выполнять такие общие функции, как доступ к файлам, выделение памяти или взаимодействие с системой графических окон.В то время как код, скажем, для Windows XP и Solaris x86 должен быть скомпилирован с одним и тем же набором инструкций машинного кода, код должен будет совершать различные вызовы для взаимодействия с ОС.

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

0 голосов
/ 16 февраля 2014

Ваш вопрос: «То есть один и тот же машинный код должен работать на каждой ОС, если это одна и та же архитектура?»это неверно.Машинный код работает на оборудовании, а не на операционной системе.ОС предоставляет сервисы для пользовательской / системной программы, и эти сервисы реализуются по-разному в каждой ОС.Скажем, ради аргумента: если вы возьмете машинный код вашей программы из ОС «X» на арке «А» и передадите его непосредственно в систему с ОС «Y» с такой же аркой «А», процессор сможетвыполнить инструкции, но это может (и почти всегда) приведет к сбою вашей программы (из-за различных проблем с реализацией, о которых уже упоминали другие).

0 голосов
/ 10 ноября 2010

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

0 голосов
/ 10 ноября 2010

Да Машинный код запускается непосредственно процессором.Но даже 32-битный набор команд "x86", который является машинным кодом, претерпел изменения в течение многих лет.Но в целом код, скомпилированный для архитектуры, должен работать на других системах.Более важной проблемой было бы то, какой компилятор и ОС были скомпилированы в

...