Перечислим ряд действий, которые выполняет exec(2) для запуска новой программы:
□ Производит трансляцию имени файла. В результате возвращается индексный дескриптор, с помощью которого осуществляется доступ к файлу. При этом проверяются права доступа.
□ Считывает заголовок файла и проверяет, является ли файл исполняемым. Вызов exec(2) также распознает скрипты, о которых говорилось в главе 1. При этом он анализирует первую строку скрипта, которая обычно имеет вид #!shellname
. В этом случае exec(2) запускает программу, указанную shellname, передавая ей в качестве аргумента имя скрипта. Если исполняемый файл (т.е. файл с установленным атрибутом x) не является бинарным и не содержит в первой строке названия интерпретатора, exec(2) запускает интерпретатор по умолчанию ( /bin/sh, /usr/bin/sh, или /usr/bin/ksh, как предписывает стандарт XPG4), передавая ему содержимое файла в качестве ввода.
□ Если исполняемый файл имеет атрибуты SUID или SGID, exec(2) соответствующим образом изменяет эффективные идентификаторы UID и GID для этого процесса. [40] Напомним, что в этом случае EUID и EGID не наследуются от родительского процесса, а присваиваются равными идентификаторам UID и GID исполняемого файла.
□ Сохраняет аргументы вызова exec(2) и переменные окружения в адресном пространстве ядра, поскольку адресное пространство процесса будет уничтожено.
□ Резервирует место в области свопинга для сегмента данных и стека.
□ Освобождает старые области процесса и соответствующие области свопинга. Если процесс был создан вызовом vfork(2) , старое адресное пространство возвращается родителю.
□ Размещает и инициализирует карты отображения для новых сегментов кода, данных и стека. Если сегмент кода является активным, например, какой-либо процесс уже выполняет эту программу, данная область используется совместно. В противном случае область заполняется содержимым соответствующего раздела исполняемого файла или инициализируется нулями для неинициализированных данных. Поскольку управление памятью процесса построено на механизме страничного замещения по требованию, копирование происходит постранично и только тогда, когда процесс обращается к страницам, отсутствующим в памяти.
□ Копирует сохраненные аргументы и переменные окружения в новый стек процесса.
□ Устанавливает обработку всех сигналов на умалчиваемые значения, поскольку процесс теперь не имеет требуемых обработчиков. Установки для игнорируемых и заблокированных сигналов не изменяются.
□ Инициализирует аппаратный контекст процесса. В частности, после этого указатель инструкций адресует точку входа новой программы.
В случае, когда программа использует динамические библиотеки, соответствующий раздел исполняемого файла (для файла формата ELF данный раздел имеет тип INTERP
) содержит имя редактора связей динамической библиотеки. В этом случае редактор связей должен быть запущен до начала выполнения основной программы для связывания с программами требуемых динамических библиотек. Таким образом точка входа в программу устанавливается на точку входа в редактор связей. После завершения своей работы редактор связей, в свою очередь, запускает программу самостоятельно, анализируя заголовок исполняемого файла. Стадии запуска новой программы проиллюстрированы на рис. 3.16.
Рис. 3.16. Запуск новой программы: а) Адресное пространство процесса до вызова exec(2) ; б) Уничтожение старого адресного пространства; в) Новое адресное пространство процесса; г) Новое адресное пространство процесса при использовании динамических библиотек
Существуют всего три события, при которых выполнение процесса переходит в режим ядра — аппаратные прерывания, особые ситуации и системные вызовы. Во всех случаях ядро UNIX получает управление и вызывает соответствующую системную процедуру для обработки события. Перед вызовом ядро сохраняет состояние прерванного процесса в системном стеке. После завершения обработки, состояние процесса восстанавливается и процесс возвращается в исходный режим выполнения. Чаще всего это режим задачи, но если, например, прерывание возникло, когда процесс уже находился в режиме ядра, после обработки события он останется в этом режиме.
Читать дальше