Листинг 3.3. ( fork.c ) Ветвление программы с помощью функции fork()
#include
#include
#include
int main() {
pid_t child_pid;
printf("The main program process ID is %d\n",
(int)getpid());
child_pid = fork();
if (child_pid != 0) {
printf("This is the parent process, with ID %d\n",
(int)getpid());
printf("The child's process ID is %d\n", (int)child_pid);
} else
printf("This is the child process, with ID %d\n",
(int)getpid());
return 0;
}
Семейство функций exec()
Функции семейства exec()заменяют программу, выполняющуюся в текущем процессе, другой программой. Когда программа вызывает функцию exec(), ее выполнение немедленно прекращается и начинает работу новая программа.
Функции, входящие в семейство exec(), немного отличаются друг от друга по своим возможностям и способу вызова.
■ Функции, в названии которых присутствует суффикс 'p'( execvp()и execlp()), принимают в качестве аргумента имя программы и ищут эту программу в каталогах, определяемых переменном среды PATH. Всем остальным функциям нужно передавать полное путевое имя программы.
■ Функции, в названии которых присутствует суффикс 'v'( execv(), execvp()и execve()), принимают список аргументов программы в виде массива строковых указателей, оканчивающегося NULL-указателем. Функции с суффиксом 'l'( execl(), execlp()и execle()) принимают список аргументов переменного размера.
■ Функции, в названии которых присутствует суффикс 'e'( execve()и execle()), в качестве дополнительного аргумента принимают массив переменных среды. Этот массив содержит строковые указатели и оканчивается пустым указателем. Каждая строка должна иметь вид " ПЕРЕМЕННАЯ = значение ".
Поскольку функция exec()заменяет одну программу другой, она никогда не возвращает значение — только если вызов программы оказался невозможен в случае ошибки.
Список аргументов, передаваемых программе, аналогичен аргументам командной строки, указываемым при запуске программы в интерактивном режиме. Их тоже можно получить с помощью параметров argcи argvфункции main(). Не забывайте, когда программу запускает интерпретатор команд, первый элемент массива argv будет содержать имя программы, а далее будут находиться переданные программе аргументы. Аналогичным образом следует поступить, формируя список аргументов для функции exec().
Совместное использование функций fork() и exec()
Стандартная методика запуска одной программы из другой такова: сначала с помощью функции fork()создается дочерний процесс, затем в нем вызывается функция exec(). Это позволяет главной программе продолжать выполнение в родительском процессе.
Программа, показанная в листинге 3.4, отображает содержимое корневого каталога с помощью команды ls, как и программа в листинге 3.2. Но на этот раз команда lsвызывается не из интерпретатора, а напрямую; ей передаются аргументы -lи /.
Листинг 3.4. ( fork-exec.с ) Совместное использование функций fork()и exec()
#include
#include
#include
#include
/* Запуск дочернего процесса в виде новой программы. Параметр
PROGRAM — это имя вызываемой программы; ее поиск будет
осуществляться в каталогах, определяемых переменной среды PATH.
Параметр ARG_LIST -- это список строковых аргументов,
передаваемых программе (должен оканчиваться указателем NULL).
Функция возвращает идентификатор порожденного процесса. */
int spawn(char* program, char** arg_list) {
pid_t child_pid;
/* Создание копии текущего процесса. */
child_pid = fork();
if (child_pid != 0)
/* Это родительский процесс. */
return child_pid;
else {
/* Выполнение указанной программы. */
execvp(program, arg_list);
/* Функция execvp() возвращает значение только в случае
ошибки. */
fprintf(stderr, "an error occurred in execvp\n");
abort();
}
}
int main() {
/* Список аргументов, передаваемых команде ls. */
char* arg_list[] = {
"ls", /* argv[0] -- имя программы. */
"-l",
NULL /* Список аргументов должен оканчиваться указателем
NULL. */
};
/* Порождаем дочерний процесс, который выполняет команду ls.
Игнорируем возвращаемый идентификатор дочернего процесса. */
Читать дальше