Вход/Регистрация
UNIX — универсальная среда программирования
вернуться

Керниган Брайан Уилсон

Шрифт:

$ waitfile troff .out echo troff done &

Программа

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

/* waitfile: wait until file stops changing */

#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) { /* copy file */

execlp("cat", "cat", argv[1], (char*)0);

error("can't execute cat %s", argv[1]);

 } else { /* run process */

execvp(argv[2], &argv[2]);

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

 }

 exit(0);

}

Мы рассмотрели пример работы как

execlp
, так и
execvp
. Эта программа выбрана в качестве иллюстрации, поскольку она весьма полезна, но возможны и другие варианты. Так,
waitfile
могла бы просто завершиться по окончании изменения файла.

Упражнение 7.17

Модифицируйте

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

Управление процессами:
fork
и
wait

Следующий шаг — вновь получить управление после запуска программы с помощью

execlp
и
execvp
. Так как эти программы просто "перекрывают" старую программу новой, для сохранения старой требуется сначала разбить ее на две копии. Одна из копий может быть перекрыта, в то время как другая ждет новую, перекрывающую ее программу, чтобы завершиться. Разбиение выполняется с помощью системного вызова
fork
:

proc_id = fork;

Программа разбивается на две копии, каждая из которых продолжает работать. Они отличаются лишь значением, возвращаемым

fork
, — номером процесса
process-id
. В первом процессе (потомке)
proc_id
равен нулю, во втором (родительском)
proc_id
есть номер процесса-потомка. Итак, вызвать другую программу и вернуться можно следующим образом:

if (fork == 0)

 execlp("/bin/sh", "sh", "-с", commandline, (char*)0);

Фактически этого достаточно, за исключением обработки ошибок.

Fork
делает две копии программы. В процессе-потомке
fork
возвращает нуль, так что он вызывает
execlp
, которая выполняет
commandline
и затем завершается. В родительском процессе
fork
возвращает не нуль, поэтому
execlp
пропускается. (При наличии ошибки
fork
возвращает -1-)

Чаще родительский процесс ожидает, пока потомок закончит работу, прежде чем продолжить свое выполнение, для чего используется системный вызов

wait
:

int status;

if (fork == 0)

 execlp(...); /* потомок */

wait(&status); /* родитель */

Однако при этом не контролируются ошибки, такие, как сбои

execlp
и
fork
, или возможность одновременной работы нескольких процессов-потомков (
wait
возвращает номер завершившегося процесса-потомка, если вы хотите сравнить его со значением, возвращенным
fork
). Тем не менее эти три строки являются сердцевиной стандартной функции
system
.

  • Читать дальше
  • 1
  • ...
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: