Книга: Linux программирование в примерах

1.1.3. Исполняемые файлы

1.1.3. Исполняемые файлы

Помните, мы говорили, что операционная система на накладывает структуру на файлы? Мы уже видели, что это было невинной ложью относительно каталогов. Это же относится к двоичным исполняемым файлам. Чтобы запустить программу, ядро должно знать, какая часть файла представляет инструкции (код), а какая — данные. Это ведет к понятию формата объектного файла, которое определяет, как эти данные располагаются внутри файла на диске.

Хотя ядро запустит лишь файлы, имеющие соответствующий формат, создание таких файлов задача утилит режима пользователя. Компилятор с языка программирования (такого как Ada, Fortran, С или С++) создает объектные файлы, а затем компоновщик или загрузчик (обычно с именем ld) связывает объектные файлы с библиотечными функциями для окончательного создания исполняемого файла. Обратите внимание, что даже если все нужные биты в файле размешены в нужных местах, ядро не запустит его, если не установлен соответствующий бит, разрешающий исполнение (или хотя бы один исполняющий бит для root).

Поскольку компилятор, ассемблер и загрузчик являются инструментами режима пользователя, изменить со временем по мере необходимости форматы объектных файлов (сравнительно) просто; надо только «научить» ядро новому формату, и он может быть использован. Часть ядра, загружающая исполняемые файлы, относительно невелика, и это не является невозможной задачей. Поэтому форматы файлов Unix развиваются с течением времени. Первоначальный формат был известен как a.out (Assembler OUTput — вывод сборщика). Следующий формат, до сих пор использующийся в некоторых коммерческих системах, известен как COFF (Common Object File Format — общий формат объектных файлов), а современный, наиболее широко использующийся формат — ELF (Extensible Linking Format — открытый формат компоновки). Современные системы GNU/Linux используют ELF.

Ядро распознает, что исполняемый файл содержит двоичный объектный код, проверяя первые несколько байтов файла на предмет совпадения со специальными магическими числами. Это последовательности двух или четырех байтов, которые ядро распознает в качестве специальных. Для обратной совместимости современные Unix-системы распознают несколько форматов. Файлы ELF начинаются с четырех символов «177ELF».

Помимо двоичных исполняемых файлов, ядро поддерживает также исполняемые сценарии (скрипты). Такой файл также начинается с магического числа: в этом случае, это два обычных символа # ! . Сценарий является программой, исполняемой интерпретатором, таким, как командный процессор, awk, Perl, Python или Tcl. Строка, начинающаяся с #!, предоставляет полный путь к интерпретатору и один необязательный аргумент:

#! /bin/awk -f
BEGIN {print "hello, world"}

Предположим, указанное содержимое располагается в файле hello.awk и этот файл исполняемый. Когда вы набираете 'hello.awk', ядро запускает программу, как если бы вы напечатали '/bin/awk -f hello.awk'. Любые дополнительные аргументы командной строки также передаются программе. В этом случае, awk запускает программу и отображает общеизвестное сообщение hello, world.

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

Оглавление книги


Генерация: 0.085. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз