Почему исполняемые файлы в операционной системе машинного кода зависят?
в windows, когда я компилирую простую программу "C", я получаю окончательный исполняемый машинный код .exe
.
То же самое, что использование gcc в unix дает .out
файл машинного кода.
в чем разница между ними?
мой основной вопрос, .exe
и .out
будучи машинными кодами, почему они зависят от операционной системы?
как в Unix я не могу выполнить .exe
прямо и в Windows, я не могу выполнить .out
Unix. Почему это так?
3 ответов
все это связано с тем, как программа загружается.
Windows и Linux имеют разные форматы для того, как они хотят, чтобы программа определяла себя.
в Linux эльф формат обычно используется. Для Windows это PE.
эти форматы определяют различные данные о программе, которая необходима для выполнения инструкций машины.
кроме того, интерфейсы операционной системы разные, поэтому разные библиотеки нуждаются быть использованы и различные системные вызовы должны быть сделаны.
для простой программы, вы можете просто перекомпилировать в другой операционной системе, чтобы она работала на обоих, но вы не сможете использовать один файл на обоих.
операционная система абстрагирует доступ к аппаратной, и делает его доступным для программистов через системные вызовы. В Windows это делается через API Windows (который обычно дополнительно абстрагируется библиотеками, которые упрощают программирование, например MFC и т. д.). В UNIX это часто делается через прерывания, которые библиотека c системы делает немного проще, следуя api POSIX (часто с несколькими системно-зависимыми дополнениями).
например, в Linux, системные вызовы выполняются через int 0x80
, с несколькими регистрами, загружаемыми аргументами функции, и библиотека C упрощает это, позволяя вам вызывать, например read
, с ожидаемыми аргументами ( int fd, void *buf, size_t count )
. Это преобразуется в вызов прерывания, на которые ядро реагирует.
эти два способа выполнения запросов к операционной системе несовместимы, и поэтому вы (как правило) не можете запускать исполняемый файл Windows в системах UNIX, и наоборот, без использования какой-либо дополнительной системы, которая действует как слой перевода, например WINE, VMWare и т. д. (хотя то, как эти два работают, очень отличается).
(кстати, a.out
ничего не говорит о содержимом исполняемого файла; это традиционное имя файла, данное исполняемым файлам, скомпилированным в системах UNIX, и является коротким для "вывода ассемблера". GCC позволяет перекрестную компиляцию, так что вы можете даже компилировать Win32-совместимый .EXE файлы с ним. Вы можете использовать -o
флаг для gcc, чтобы указать выходное имя файла, которое показывает, что оно не имеет отношения к фактическому формату выводимого файла.)
в среде unix любой файл, имеющий бит +x, считается исполняемым. Помните, что даже не двоичные файлы могут быть исполняемыми (сценарии оболочки, пакетные файлы и т. д...). Windows опирается на концепцию расширения файла, на Unix мы просто установили chmod +x filename
.
вы всегда можете использовать -o file
флаг, чтобы заставить gcc производить любое имя файла, которое вам нравится.