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

9.1.4.1. Системный вызов execve()

9.1.4.1. Системный вызов execve()

Простейшей для объяснения функцией является execve(). Она является также лежащим в основе системным вызовом. Другие являются функциями-оболочками, как вскоре будет объяснено.

int execve(const char *filename, char *const argv[],
 char* const envp[]);
filename
является именем программы для исполнения. Это может быть именем полного или относительного пути. Файл должен иметь формат исполняемого файла, который понимает ядро. Современные системы используют формат исполняемого файла ELF (Extensible Linking Format — открытый формат компоновки). GNU/Linux распознает ELF и несколько других форматов. С помощью execve() можно исполнять интерпретируемые сценарии, если они используют особую первую строку с именем интерпретатора, начинающуюся с '#!'. (Сценарии, которые не начинаются с '#!', потерпят неудачу.) В разделе 1.1.3 «Исполняемые файлы» представлен пример использования '#!'. argv является стандартным списком аргументов С — массив символьных указателей на строки аргументов, включая значение для использования сargv[0][90], завершающийся указателем NULL.

envp является окружением для использования новым процессом, с таким же форматом, как глобальная переменная environ (см. раздел 2.4 «Переменные окружения»). В новой программе это окружение становится начальным значением environ.

Программа не должна возвращаться из вызова exec(). Если она возвращается, возникла проблема. Чаще всего либо не существует затребованная программа, либо она существует, но не является исполняемой (значения для errno ENOENT и EACCESS соответственно). Может быть множество других ошибок; см. справочную страницу execve(2).

В предположении, что вызов был успешным, текущее содержимое адресного пространства процесса сбрасывается. (Ядро сначала сохраняет в безопасном месте данные argv и envp.) Ядро загружает для новой программы исполняемый код вместе со всеми глобальными и статическими переменными. Затем ядро инициализирует переменные окружения переданными execve() данными, а далее вызывает процедуру main() новой программы с переданным функции execve() массивом argv. Подсчитывается число аргументов и это значение передается main() в argc.

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

exec() для процесса можно сравнить с ролями, которые играют в жизни люди. В различное время в течение дня один человек может быть родителем, супругом, другом, студентом или рабочим, покупателем в магазине и т.д. Это одна и та же личность, исполняющая различные роли. Также и процесс — его PID, открытые файлы, текущий каталог и т.п. — не изменяются, тогда как выполняемая работа - запущенная с помощью exec() программа — может измениться.

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


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