Системное программирование в UNIX средствами Free Pascal

Для семейства вызовов linuxexecl аргументы


uses stdio;
(* Для семейства вызовов linuxexecl аргументы должны быть списком,
   заканчивающимся NULL *)
function linuxexecl(path:pchar;arg0:pchar;argv:array of const):integer;
function linuxexeclp(fname:pchar;arg0:pchar;argv:array of const):integer;
(* Вызову execl нужно передать полный путь к файлу программы *)
Procedure Execl(Path:pathstr);
(* Вызову execle нужно передать полный путь к файлу программы
   и массив указателей на строки окружения *)
Procedure Execle(Path:pathstr; Envp:ppchar);
(* Вызову ехесlp нужно только имя файла программы *)
Procedure Execlp(Path:pathstr);
(* Семейству вызовов execv нужно передать массив аргументов *)


(* Вызову execv нужно передать полный путь к файлу программы *)
Procedure Execv(Path:pathstr;argv:ppchar);
(* Вызову execvp нужно только имя файла программы *)
Procedure Execvp(Path:pathstr;argv:ppchar);
(* Вызову execve нужно передать полный путь к файлу программы
   и массив указателей на строки окружения *)
Procedure Execve(Path:pchar;argv:ppchar;envp:ppchar);
Procedure Execve(Path:pathstr;argv,envp:ppchar);

execl
execle
execlp
v
v
execv
execvp
execve

Рис. 5.2. Дерево семейства вызовов ехес
Все множество системных вызовов ехес выполняет одну и ту же функцию: они преобразуют вызывающий процесс, загружая новую программу в его пространство памяти. Если вызов ехес завершился успешно, то вызывающая программ полностью замещается новой программой, которая запускается с начала. Результат вызова можно рассматривать как запуск нового процесса, который при этом сохраняет идентификатор вызывающего процесса и по умолчанию наследует файловые дескрипторы (см. пункт 5.5.2).
Важно отметить, что вызов ехес не создает новый подпроцесс, который выполняется одновременно с вызывающим, а вместо этого новая программа загружается на место старой. Поэтому, в отличие от вызова fork, успешный вызов ехеc не возвращает значения.


Для простоты осветим только один из вызовов ехес, а именно linuxexecl.
Все аргументы функции linuxexecl являются указателями строк. Первый из них, аргумент path, задает имя файла, содержащего программу, которая будет запущена на выполнение; для вызова linuxexecl это должен быть полный путь к программе, абсолютный или относительный. Сам файл должен содержать программу или последовательность команд оболочки и быть доступным для выполнения. Система определяет, содержит ли файл программу, просматривая его первые байты (обычно первые два байта). Если они содержат специальное значение, называемое магическим числом (magic number), то система рассматривает файл как программу. Второй аргумент, arg0, является, по соглашению, именем программы или команды, из которого исключен путь к ней. Этот аргумент и оставшееся переменное число аргументов (массив args) доступны в вызываемой программе, аналогично аргументам командной строки при запуске программы из оболочки. В действительности командный интерпретатор сам вызывает команды, используя один из вызовов ехес совместно с вызовом fork. Так как список аргументов имеет произвольную длину, он должен заканчиваться нулевым указателем для обозначения конца списка.
Короткий пример ценнее тысячи слов – следующая программа использует вызов execl для запуска программы вывода содержимого каталога ls:
(* Программа runls - использование "execl" для запуска ls *)
uses linux,stdio;
begin
  writeln('Запуск программы ls');
  execl('/bin/ls -l');
  (* Если execl возвращает значение, то вызов был неудачным *)
  perror ('Вызов execl не смог запустить программу ls');
  halt(1);
end.
Работа этой демонстрационной программы показана на рис. 5.3. Часть До показывает процесс непосредственно перед вызовом execl. Часть После
показывает измененный процесс после вызова execl, который при этом выполняет программу ls. Программный счетчик PC указывает на первую строку программы ls, показывая, что вызов execl запускает программу с начала.



writeln(...);
< PC
execl('/bin/ls -l');
runls

exec
До
После
(* 1-ая строка ls*)
< PC
Команда ls

Рис. 5.3. Вызов exec
Обратите внимание, что в примере за вызовом execl следует безусловный вызов библиотечной процедуры perror. Это отражает то, что успешный вызов функции execl (и других родственных функций) стирает вызывающую программу. Если вызывающая программа сохраняет работоспособность и происходит возврат из вызова execl, значит, произошла ошибка. Поэтому возвращаемое значение execl и родственных функций всегда равно -1.

Содержание раздела