Главная » Программирование для UNIX » Процессы в системе UNIX

0

Этот  раздел описывает выполнение одной  программы из  другой. Самый  простой способ  сделать это –  обратиться к стандартной библиотечной функции system, описанной, но осужденной в главе 6. Команда system получает один  аргумент – командную строку точно  в том виде,  как она  набрана на  терминале (за  исключением символа новой  строки в конце), и выполняет ее в подоболочке. Если  командная строка должна быть составлена из нескольких частей, то могут  пригодиться   возможности   форматирования  в   памяти,  которыми   обладает sprintf. В конце данного раздела будет представлена более  надежная версия system  для  использования в  интерактивных  программах, но сначала надо исследовать части, из которых она состоит.

Низкоуровневое создание процессов – execlp и execvp

Базовая операция – это выполнение другой программы без ожидания завершения системным вызовом execlp. Например, чтобы напечатать дату  в качестве последнего действия выполняющейся программы, используйте

execlp("date", "date",  (char *)  0);

Первый аргумент execlp  –  это  имя  файла  команды; execlp  получает путь поиска (т. е. $PATH) из окружения и осуществляет такой же поиск, как оболочка. Второй  и последующие аргументы – это имя  команды и ее  параметры;  они  становятся массивом argv  для  новой  программы. Конец списка помечен нулевым  значением (чтобы  понять конструкцию execlp, обратитесь к exec(2)).

Вызов execlp перекрывает существующую программу новой, запускает ее  и  выходит.  Первичная  программа получает управление  обратно только в случае ошибки, например, если файл не найден или  не является выполняемым:

execlp("date", "date",  (char *)  0);

fprintf(stderr,  "Couldn’t  execute  ‘date’\n"), exit(l);

Разновидность execlp, именуемая execvp, применяется в тех  случаях, когда количество аргументов заранее не известно. Вызов выглядит так:

execvp(filename, argp);

где argp  – это массив указателей на аргументы (как argv);  последний указатель в массиве должен быть NULL, чтобы  execvp имел возможность определить, где  кончается  список.  Как   и  для  execlp,  filename  –  это файл, в котором находится программа, а argp  – это массив argv для новой программы; argp[0] – это имя  программы.

Ни одна из этих  программ не допускает наличия метасимволов <, >, *, кавычек и т. д. в списке аргументов. Если  это необходимо, вызывайте посредством execlp  оболочку /bin/sh, которая  выполнит всю  работу. Сформируйте командную строку, которая будет содержать всю команду, как если бы она была  напечатана на терминале, затем скажите:

execlp("/bin/sh", "sh", "–c", commandline,  (char *)  0);

Аргумент –с определяет, что следующий аргумент должен рассматриваться как целая командная строка, а не как отдельный аргумент.

Рассмотрим в качестве иллюстрации программу waitfile. Команда

$ waitfile  имя5файла [ команда ]

периодически проверяет указанный файл. Если он не изменился с момента последней проверки, то команда выполняется. Если команда не определена, то  файл копируется на  стандартное устройство вывода. Для мониторинга работы troff мы используем waitfile:

$ waitfile  troff.out echo troff done &

Реализация waitfile извлекает время  изменения  файла при  помощи

fstat.

/*  waitfile:  ждет,  пока файл не перестанет  изменяться  */

#include <stdio.h>

#include <sys/types.h>

#include  <sys/stat.h> char  *progname;

main(argc,  argv) int  argc;

char  *argv[];

{

int fd;

struct  stat  stbuf; time_t  old_time  =  0;

progname  =  argv[0]; if  (argc  <  2)

error("Usage: %s  filename  [cmd]",  progname); if ((fd =  open(argv[1], 0))  ==  –1)

error("can’t  open  %s",  argv[1]); fstat(fd,  &stbuf);

while  (stbuf.st_mtime  !=  old_time)  { old_time  =  stbuf.st_mtime; sleep(60);

fstat(fd, &stbuf);

}

if  (argc == 2)  {        /*  копировать  файл  */ execlp("cat",  "cat", argv[1],  (char *)  0); error("can’t  execute  cat  %s",  argv[1]);

} else {                       /*  запустить  процесс */ execvp(argv[2],  &argv[2]);

error("can’t execute  %s",  argv[2]);

} exit(0);

}

Тут проиллюстрированы оба вызова: execlp и execvp.

Выбран именно такой подход, потому  что он полезен для  понимания, но приемлемы и  другие  варианты. Например, waitfile  может  просто  завершаться, после того как файл перестал изменяться.

Упражнение 7.17.   Измените программу  watchfile  (упражнение 7.12) таким образом, чтобы  она  имела те же  свойства, что и waitfile: если  нет параметра команда, она копирует файл; в ином  случае выполняет команду. Могут ли watchfile и waitfile совместно использовать исход ный код?  Подсказка: argv[0]. ~

Источник: Керниган Б., Пайк Р., UNIX. Программное окружение. – Пер. с англ. – СПб: Символ-Плюс, 2003. – 416 с., ил.

По теме:

  • Комментарии