Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учеб.пос.СП.doc
Скачиваний:
28
Добавлен:
31.03.2015
Размер:
1.33 Mб
Скачать

2.10. Системный вызов lseek

Системный вызов lseek используется для переустановки текущей позиции в файле. Он не выполняет никаких операций ввода-вывода и не отдает команд контроллеру диска.

Lseek - устанавливает и возвращает текущую позицию в файле.

#include <unistd.h>

off_t lseek(

int fd, /* дескриптор файла */

off_t pos, /* позиция в файле */

int whence /* интерпретация аргумента pos */

);

/* Возвращает новую позицию в файле или -1 в случае ошибки (код ошибки в переменной errno) */

Аргумент whence может принимать одно из следующих значений:

  • SEEK_SET - аргумент pos содержит смещение от начала файла (абсолютная позиция в файле).

  • SEEK_CUR - аргумент pos содержит смещение от текущей позиции в файле. Может быть положительным числом, нулем и отрицательным числом. Указав в аргументе pos значение 0 - получим текущую позицию в файле.

  • SEEK_END - аргумент pos содержит смещение от конца файла. Может быть положительным числом, нулем и отрицательным числом. Указав в аргументе pos значение 0 - мы установим текущую позицию в конец файла.

Результатом работы вызова может быть любое неотрицательное число, даже превышающее размер файла. Если новая текущая позиция оказалась за пределами файла, ближайший вызов write вставит недостающий кусок в конец файла и заполнит его байтами со значением 0. Вызов read, с текущей позицией, установленной в конец файла или за его пределами, вернет признак конца файла - 0. Попытка чтения из интервала, который заполнил вызов write при вставке недостающего куска, увенчается успехом и в вызывающую программу будет возвращен буфер, заполненный нулями, как того и следовало ожидать. Из всех возможных вариантов вызова lseek, наиболее часто используются следующие:

  1. для установки абсолютной позиции в файле: lseek(fd, offset, SEEK_SET);

  2. для перемещения в конец файла: lseek(fd, 0, SEEK_END);

  3. для получения текущей позиции в файле:

off_t where;

where = lseek(fd, 0, SEEK_CUR);

Большая часть операций по установке текущей позиции в файле выполняется ядром неявно. Так, вызов open устанавливает текущую позицию на первый байт в файле. Вызовы read и write увеличивают значение текущей позиции на количество прочитанных или записанных байт. Когда файл открывается с флагом O_APPEND, текущая позиция переустанавливается в конец файла перед каждым вызовом write.

2.11. Системные вызовы pread и pwrite

Pread - выполняет чтение из файла, начиная с заданной позиции:

#include <unistd.h>

ssize_t pread(

int fd, /* дескриптор файла*/

void *buf, /* адрес буфера для принимаемых данных*/

size_t nbytes, /* объем принимаемых данных */

off_t offset /* позиция в файле*/

);

/* Возвращает количество прочитанных байт или -1 в случае ошибки (код ошибки в переменной errno) */

Pwrite - выполняет запись в файл, в заданную позицию:

#include <unistd.h>

ssize_t pwrite(

int fd, /* дескриптор файла*/

const void *buf, /* адрес буфера с данными для записи*/

size_t nbytes, /* количество данных для записи */

off_t offset /* позиция в файле*/

);

/* Возвращает количество записанных байт или -1 в случае ошибки (код ошибки в переменной errno) */

Системные вызовы pread и pwrite по своей функциональности практически полностью совпадают с комбинацией вызова read или write соответственно, за исключением:

  • они не пользуются текущей позицией в файле, так как позиция для записи или чтения передается явно, через аргумент offset;

  • они не изменяют текущую позицию в файле. Фактически, текущая позиция полностью игнорируется этими вызовами.

Удобство применения одного вызова вместо двух неоспоримо, но, что более важно, вызовам pread и pwrite несвойственны проблемы, связанные с изменением текущей позиции в файле между lseek и последующими вызовами read или write из другого процесса или потока.