Чтение онлайн

на главную - закладки

Жанры

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
.

Значение

status
, возвращаемое
wait
, содержит в своих младших восьми разрядах системное представление кода завершения процесса-потомка; оно равно нулю при нормальном завершении и не равно нулю при разного рода затруднениях. Следующие старшие восемь битов берутся из аргумента вызова
exit
или возвращаются из
main
, которая вызывает окончание выполнения процесса-потомка.

Если программа вызывается из

shell
, три дескриптора файла, 0, 1 и 2, ссылаются на соответствующие файлы, и все остальные дескрипторы доступны для использования. Когда эта программа вызывает другую, в соответствии с профессиональной этикой указанные условия должны быть соблюдены. Ни
fork
, ни
exec
не влияют никоим образом на открытые файлы; оба процесса, родитель и потомок, имеют одни и те же открытые файлы. Если процесс-родитель буферизует выходной поток, который необходимо вывести до процесса-потомка, родитель должен очистить свой буфер ранее
execlp
. И, наоборот, при буферизации родителем входного потока потомок потеряет информацию, которая читалась родителем. Выходной поток может быть выведен, но входной нельзя "положить назад". Обе ситуации являются следствием реализации входного или выходного потока стандартной библиотекой ввода-вывода, обсуждавшейся в гл. 6, поскольку при этом и ввод, и вывод буферизуются обычным образом.

Именно свойство наследования дескрипторов файлов через

execlp
используется в
system
: если у вызывающей программы стандартные входной и выходной потоки не связаны с терминалом, то этим же свойством обладает команда, вызванная из
system
. Возможно, такой вариант нам и нужен. В списке команд редактора
ed
, например, входной поток команды, начинающейся с символа
!
, вероятно, должен поступить из того же списка. Даже тогда
ed
должен считывать из своего входного потока по одному символу во избежание возникновения проблем буферизации ввода.

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

Сирота

Шмаков Алексей Семенович
1. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Сирота

Ворон

LizaMoloko
Фантастика:
попаданцы
фэнтези
гаремник
5.00
рейтинг книги
Ворон

Седина в бороду, Босс… вразнос!

Трофимова Любовь
Юмор:
юмористическая проза
5.00
рейтинг книги
Седина в бороду, Босс… вразнос!

Первый среди равных. Книга IX

Бор Жорж
9. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IX

Кодекс Охотника

Винокуров Юрий
1. Кодекс Охотника
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
боевая фантастика
5.00
рейтинг книги
Кодекс Охотника

Чужое наследие

Кораблев Родион
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Чужое наследие

1941, Великая Отечественная катастрофа: Итоги дискуссии

Коллектив авторов
Документальная литература:
военная документалистика
6.25
рейтинг книги
1941, Великая Отечественная катастрофа: Итоги дискуссии

Богам – божье, людям – людское

Красницкий Евгений Сергеевич
6. Отрок
Приключения:
исторические приключения
8.83
рейтинг книги
Богам – божье, людям – людское

Твое сердце будет разбито. Книга 1

Джейн Анна
Любовные романы:
современные любовные романы
5.50
рейтинг книги
Твое сердце будет разбито. Книга 1

Набирая силу

Рокотов Алексей
2. Путь князя
Фантастика:
фэнтези
5.00
рейтинг книги
Набирая силу

Газлайтер. Том 2

Володин Григорий
2. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 2

Автобиография

Твен Марк
Документальная литература:
биографии и мемуары
6.25
рейтинг книги
Автобиография

Мастер решений

Земляной Андрей Борисович
3. Специалист по выживанию
Фантастика:
боевая фантастика
космическая фантастика
6.20
рейтинг книги
Мастер решений

Кодекс Крови. Книга ХII

Борзых М.
12. РОС: Кодекс Крови
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Кодекс Крови. Книга ХII