Язык программирования Си


         

Для иллюстрации приведем упрощенную версию


Для иллюстрации приведем упрощенную версию программы cp системы UNIX, которая копирует один файл в другой. В нашей версии копируется только один файл, не позволяется во втором аргументе указывать директорий (каталог), и права доступа не копируются, а задаются константой.

#include <stdio.h> #include <fcntl.h> #include "syscalls.h" #define PERMS 0666 /* RW для собственника, группы и остальных */

void error(char *, ...);

/* cp: копирование f1 в f2 */ main(int argc, char *argv[]) { int f1, f2, n; char buf[BUFSIZ];

if (argc ! = 3) error("Обращение: cp откуда куда"); if ((f1 = open(argv[1], O_RDONLY, 0)) == -1) error("cp: не могу открыть файл %s", argv[1]); if ((f2 = creat(argv[2], PERMS)) == -1) error("cp: не могу создать файл %s, режим %03o", argv[2], PERMS); while ((n = read(f1, buf, BUFSIZ)) > 0) if (write(f2, buf, n) != n) error ("cp: ошибка при записи в файл %s", argv[2]); return 0; }

Данная программа создаст файл вывода с фиксированными правами доступа, определяемыми кодом 0666. С помощью системного вызова stat, который будет описан в параграфе 8.6, мы можем определить режим использования существующего файла и задать тот же режим для копии.

Заметим, что функция error, вызываемая с различным числом аргументов, во многом похожа на printf. Реализация error иллюстрирует, как пользоваться другими программами семейства printf. Библиотечная функция vprintf аналогична printf, с той лишь оговоркой, что переменная часть списка аргументов заменена в ней одним аргументом, который инициализируется макросом va_start. Подобным же образом соотносятся функции vfprinf с fprintf и vsprintf с sprintf.

#include <stdio.h> #include <stdarg.h>

/* error: печатает сообщение об ошибке и умирает */ void error(char *fmt, ...) { va_list args;

va_start(args, fmt); fprintf(stderr, "ошибка: "); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); exit(1); }

На количество одновременно открытых в программе файлов имеется ограничение (обычно их число колеблется около 20). Поэтому любая программа, которая намеревается работать с большим количеством файлов, должна быть готова повторно использовать их дескрипторы. Функция close(int fd) разрывает связь между файловым дескриптором и открытым файлом и освобождает дескриптор для его применения с другим файлом. Она аналогична библиотечной функции fclose с тем лишь различием, что никакой очистки буфера не делает. Завершение программы с помощью exit или return в главной программе закрывает все открытые файлы.

Функция unlink(char *name) удаляет имя файла из файловой системы. Она соответствует функции remove стандартной библиотеки.

Упражнение 8.1. Перепишите программу cat из главы 7, используя функции read, write, open и close. Замените ими соответствующие функции стандартной библиотеки. Поэкспериментируйте, чтобы сравнить быстродействие двух версий.


Содержание  Назад  Вперед