Выбрать главу

В листинге 3.3 приведен пример ветвления программы с помощью функции fork(). Учтите, что первая часть инструкции if выполняется только в родительском процессе, тогда как ветвь else — только в дочернем.

Листинг 3.3. (fork.c) Ветвление программы с помощью функции fork()

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

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 <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

/* Запуск дочернего процесса в виде новой программы. Параметр

   PROGRAM — это имя вызываемой программы; ее поиск будет

   осуществляться в каталогах, определяемых переменной среды PATH.

   Параметр ARG_LIST -- это список строковых аргументов,

   передаваемых программе (должен оканчиваться указателем NULL).

   Функция возвращает идентификатор порожденного процесса. */