Брайан Керниган - UNIX — универсальная среда программирования
- Название:UNIX — универсальная среда программирования
- Автор:
- Жанр:
- Издательство:Финансы и статистика
- Год:1992
- Город:Москва
- ISBN:5-289-00253-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брайан Керниган - UNIX — универсальная среда программирования краткое содержание
В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.
Для программистов-пользователей операционной системы UNIX.
UNIX — универсальная среда программирования - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
/* sv: save new files */
#include
#include
#include
#include
char *progname;
main(argc, argv)
int argc;
char *argv[];
{
int i;
struct stat stbuf;
char *dir = argv[argc-1];
progname = argv[0];
if (argc <= 2)
error("Usage: %s files... dir", progname);
if (stat(dir, &stbuf) == -1)
error("can't access directory %s", dir);
if ((stbuf.st_mode & S_IFMT) != S_IFDIR)
error("%s is not a directory", dir);
for (i = 1; i < argc-1; i++)
sv(argv[i], dir);
exit(0);
}
Значения времени, хранящиеся в индексных дескрипторах, исчисляются в секундах (за начало отсчета принято время 0:00 по Гринвичу, 1 января 1970 г.), так что более старые файлы имеют меньшие значения в поле st_mtime
.
sv(file, dir) /* save file in dir */
char *file, *dir;
{
struct stat sti, sto;
int fin, fout, n;
char target[BUFSIZ], buf[BUFSIZ], *index();
sprintf(target, "%s/%s", dir, file);
if (index(file, '/') != NULL) /* strchr() in some systems */
error("won't handle /'s in %s", file);
if (stat(file, &sti) == -1)
error("can't stat %s", file);
if (stat(target, &sto) == -1) /* target not present */
sto.st_mtime = 0; /* so make it look old */
if (sti.st_mtime < sto.st_mtime) /* target is newer */
fprintf(stderr, "%s: %s not copied\n", progname, file);
else if ((fin = open(file, 0)) == -1)
error("can't open file %s", file);
else if ((fout = creat(target, sti.st_mode)) == -1)
error("can't create %s", target);
else
while ((n = read(fin, buf, sizeof buf)) > 0)
if (write(fout, buf, n) != n)
error("error writing %s", target);
close(fin);
close(fout);
}
Мы заменили стандартные функции ввода-вывода функцией creat
, так что sv
может сохранять режим работы входного файла. (Заметьте, что index
и strchr
— разные имена одной и той же процедуры; посмотрите в справочном руководстве по string(3)
, какое имя использует ваша система.)
Хотя программа sv
довольно специфична, в ней отражены некоторые важные идеи. Многие программы не являются системными, но тем не менее используют информацию, поддерживаемую операционной системой и доступную через системные вызовы. Для таких программ существенно, что представление информации хранится только в стандартных файлах макроопределений типа и и что в программы включены эти файлы вместо действительных описаний. Подобные программы с большей степенью вероятности переносимы с одной системы на другую.
Отметим, что по крайней мере две трети кода sv
составляет контроль ошибок. На ранних этапах написания программы было искушение сэкономить на обработке ошибок, поскольку это отвлекает от основной задачи. Когда же программа уже работает, трудно решиться на то, чтобы вернуться назад и вставить в нее процедуры проверки, которые превращают специальную программу в унифицированную.
Программа sv
не защищена от возможных сбоев. Она, например, не обрабатывает прерывания в неподходящие моменты, но более аккуратна, чем большинство других программ. Хотелось бы обратить ваше внимание на финальный оператор write
. Программа редко сбивается на этом операторе, поэтому многие программы игнорируют такую возможность. Однако переполнение дискового пространства, неполадки в линии связи или иные нарушения могут вызвать ошибки в write
, и вы гораздо лучше справитесь с ними, если программа выдает вам соответствующее сообщение.
Дело в том, что контроль ошибок весьма утомителен, но тем не менее важен. Из-за ограниченного объема книги и обширности излагаемого в ней материала мы не уделяли должного внимания этому вопросу. Но в настоящих, "производственных" программах не следует позволять себе игнорировать ошибки.
Модифицируйте checkmail
так, чтобы идентифицировать посылающего сообщение: "У вас есть почта". Подсказка : sscanf
, lseek
.
Модифицируйте checkmail
так, чтобы она не переходила к каталогу почты перед входом в цикл. Окажет ли это ощутимое влияние на ее производительность? Более трудный вопрос: можете ли вы написать версию checkmail
, которая обходится только одним процессом для оповещения всех пользователей?
Напишите программу watchfile
, которая управляет файлом и печатает его с начала всякий раз, как он изменится. Когда бы вы ее использовали?
Программа sv
очень "прямолинейна" при обработке ошибок. Модифицируйте ее так, чтобы она продолжала выполняться, даже если не удается обработать некоторый файл.
Сделайте sv
рекурсивной: если один из исходных файлов — каталог, то этот каталог и все его файлы обрабатываются таким же образом. Сделайте рекурсивной cp
. Подумайте, следует ли cp
и sv
объединить в одну программу, чтобы cp -v
не создавала копию, если целевой файл новее файла-источника.
Напишите программу random
.
$ random filename
должна выдавать одну строку, произвольно выбранную из файла. Если есть файл people
, содержащий имена, random
можно использовать в программе scapegoat
("козел отпущения"), полезной при случайном определении виновных:
$ cat scapegoat
echo "В этом виноват `random people`!"
$ scapegoat
В этом виноват Кен!
$
Убедитесь в том, что random
хороша независимо от распределения длины строк.
Помимо прочего в индексном дескрипторе указаны адреса размещения блоков файла на диске. Рассмотрите файл , а затем напишите программу icat
, которая должна читать файлы, описываемые номером записи каталога и устройством диска. (Она, конечно, будет работать только в том случае, если требуемый диск открыт на чтение.) При каких обстоятельствах icat
полезна?
7.4 Процессы
В этом разделе мы покажем вам, как выполнить одну программу, вызвав ее из другой. Самый легкий путь — привлечь стандартную библиотечную программу system
, упомянутую, но забракованную в гл. 6. Программа system
использует один аргумент — командную строку в том виде, в каком она вводится с терминала (за исключением символа перевода строки), и выполняет ее порожденным shell
. Если командная строка должна быть создана из кусочков, можно прибегнуть к форматированию памяти программой sprintf
. В конце раздела мы рассмотрим более безопасную версию system
для работы с диалоговыми программами, но прежде чем изучать программу в целом, обсудим структуры, из которых она составляется.
execlp
и execvp
Самая важная операция - выполнение другой программы без возврата с помощью системного вызова execlp
. Например, чтобы напечатать дату и выполнить тем самым последнее действие запущенной программы, используют
Интервал:
Закладка: