Произвольный доступ - SEEK и LSEEK
Нормально при работе с файлами ввод и вывод осуществля- ется последовательно: при каждом обращении к функциям READ и WRITE чтение или запись начинаются с позиции, непосредствен- но следующей за предыдущей обработанной. Но при необходимос- ти файл может читаться или записываться в любом произвольном порядке. Обращение к системе с помощью функции LSEEK позво- ляет передвигаться по файлу, не производя фактического чте- ния или записи. В результате обращения
LSEEK(FD,OFFSET,ORIGIN);
текущая позиция в файле с дескриптором FD передвигается на позицию OFFSET (смещение), которая отсчитывается от места, указываемого аргументом ORIGIN (начало отсчета). Последующее чтение или запись будут теперь начинаться с этой позиции. Аргумент OFFSET имеет тип LONG; FD и ORIGIN имеют тип INT. Аргумент ORIGIN может принимать значения 0,1 или 2, указывая на то, что величина OFFSET должна отсчитываться соответст- венно от начала файла, от текущей позиции или от конца фай- ла. Например, чтобы дополнить файл, следует перед записью найти его конец:
LSEEK(FD,0L,2);
чтобы вернуться к началу ("перемотать обратно"), можно напи- сать:
LSEEK(FD,0L,0);
обратите внимание на аргумент 0L; его можно было бы записать и в виде (LONG) 0. Функция LSEEK позволяет обращаться с файлами примерно так же, как с большими массивами, правда ценой более медлен- ного доступа. следующая простая функция, например, считывает любое количество байтов, начиная с произвольного места в файле.
GET(FD,POS,BUF,N) /*READ N BYTES FROM POSITION POS*/ INT FD, N; LONG POS; CHAR *BUF; \( LSEEK(FD,POS,0); /*GET TO POS*/ RETURN(READ(FD,BUF,N)); \)
В более ранних редакциях, чем редакция 7 системы UNIX, основная точка входа в систему ввода-вывода называется SEEK. Функция SEEK идентична функции LSEEK, за исключением того, что аргумент OFFSET имеет тип INT, а не LONG. в соответствии с этим, поскольку на PDP-11 целые имеют только 16 битов, ар- гумент OFFSET, указываемый функции SEEK, ограничен величиной 65535; по этой причине аргумент ORIGIN может иметь значения 3, 4, 5, которые заставляют функцию SEEK умножить заданное значение OFFSET на 512 (количество байтов в одном физическом блоке) и затем интерпретировать ORIGIN, как если это 0, 1 или 2 соответственно. Следовательно, чтобы достичь произ- вольного места в большом файле, нужно два обращения к SEEK: сначала одно, которое выделяет нужный блок, а затем второе, где ORIGIN имеет значение 1 и которое осуществляет передви- жение на желаемый байт внутри блока.
Упражнение 8-2
--------------- Очевидно, что SEEK может быть написана в терминалах LSEEK и наоборот. напишите каждую функцию через другую.