• EACCES — аргумент pathname не указывает на обычный файл, файл не является исполняемым или запрещено чтение содержимого одного из каталогов, являющегося частью pathname (то есть для каталога не выставлен признак «на исполнение»). Как вариант, файл может храниться в файловой системе, подключенной с использованием флага MS_NOEXEC (см. подраздел 14.8.1).

• ENOENT — файл, на который ссылается pathname, не существует.

• ENOEXEC — файл, на который ссылается pathname, помечен как исполняемый, но система не распознает его формат. Возможно, это скрипт, в первой строке которого не был указан интерпретатор (такая строка должна начинаться с символов #!).

• ETXTBSY — файл, на который ссылается pathname, открыт для записи другим процессом (см. подраздел 4.3.2).

• E2BIG — общий объем памяти, требуемый для хранения списка аргументов и переменных среды, превышает допустимое ограничение.

Ошибки, перечисленные выше, могут также возникнуть в случае, если любое из этих условий будет исполнено для интерпретатора, который должен выполнить скрипт (см. раздел 27.3), или для ELF-интерпретатора, с помощью которого выполняется программа.

Формат ELF (Executable and Linking Format) является широко распространенной спецификацией, описывающей структуру исполняемый файлов. Обычно во время выполнения образ процесса строится на основе сегментов исполняемого файла (см. раздел 6.3). Однако спецификация ELF также позволяет указать интерпретатор (заголовочный элемент PT_INTERP) для выполнения программы. Если интерпретатор определен, ядро строит образ процесса из сегментов указанного исполняемого файла интерпретатора. Затем уже сам интерпретатор должен загрузить и выполнить программу. Больше о роли интерпретаторов в формате ELF можно узнать в главе 41; там же будут даны отсылки к более углубленной информации.

Пример программы

Пример использования вызова execve() показан в листинге 27.1. Данный код создает списки аргументов и переменных среды для новой программы и затем вызывает execve(), задействуя в качестве пути к исполняемому файлу аргумент командной строки (argv[1]).

В листинге 27.2 приводится программа, которая должна быть запущена кодом из предыдущего листинга. Все, что она делает, — это выводит аргументы командной строки и переменные среды (доступ к последним осуществляется посредством глобальной переменной environ, как описывается в разделе 6.7).

Работа программ из листингов 27.1 и 27.2 показана в следующей сессии командной оболочки (в этом примере для задания исполняемого файла используется относительный путь):

$ ./t_execve./envargs

argv[0] = envargs Весь этот текст выводится командой envargs

argv[1] = hello world

argv[2] = goodbye

environ: GREET=salut

environ: BYE=adieu

Листинг 27.1. Использование вызова execve() для запуска новой программы

procexec/t_execve.c

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

char *argVec[10]; /* С запасом */

char *envVec[] = { "GREET=salut", "BYE=adieu", NULL };

if (argc!= 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s pathname\n", argv[0]);

argVec[0] = strrchr(argv[1], '/');

/* Получаем последнюю часть имени файла из argv[1] */

if (argVec[0]!= NULL)

argVec[0]++;

else

argVec[0] = argv[1];

argVec[1] = "hello world";

argVec[2] = "goodbye";

argVec[3] = NULL; /* В конце списка должно быть значение NULL */

execve(argv[1], argVec, envVec);

errExit("execve"); /* Если мы сюда добрались, что-то пошло не так */

}

procexec/t_execve.c

Листинг 27.2. Вывод списка аргументов и переменных среды

procexec/envargs.c

#include "tlpi_hdr.h"

extern char **environ;

int

main(int argc, char *argv[])

{

int j;

char **ep;

for (j = 0; j < argc; j++)

printf("argv[%d] = %s\n", j, argv[j]);

for (ep = environ; *ep!= NULL; ep++)

printf("environ: %s\n", *ep);

exit(EXIT_SUCCESS);

}

procexec/envargs.c

27.2. Библиотечные функции семейства exec()

Библиотечные функции, описанные в этом разделе, предоставляют альтернативный интерфейс к операции exec(). Все они работают поверх вызова execve(), отличаются от него и различаются между собой только тем, каким образом указываются имя программы, список аргументов и переменные среды.

#include

int execle(const char *pathname, const char *arg

/*, (char *) NULL, char *const envp[] */);

int execlp(const char *filename, const char *arg

/*, (char *) NULL */);

int execvp(const char *filename, char *const argv[]);

int execv(const char *pathname, char *const argv[]);

int execl(const char *pathname, const char *arg

/*, (char *) NULL */);

Ни одна из этих функций не возвращает результат при успешном выполнении; при ошибке все они возвращают –1

Перейти на страницу:

Похожие книги