Программа waitfile
использует fstat
, чтобы выявить время последнего изменения файла.
/* waitfile: wait until file stops changing */
#include
#include
#include
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
могла бы просто завершиться по окончании изменения файла.
Модифицируйте 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
.
Значение status
, возвращаемое wait
, содержит в своих младших восьми разрядах системное представление кода завершения процесса-потомка; оно равно нулю при нормальном завершении и не равно нулю при разного рода затруднениях. Следующие старшие восемь битов берутся из аргумента вызова exit
или возвращаются из main
, которая вызывает окончание выполнения процесса-потомка.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии