Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

Системные вызовы ттар и munmap

Вернемся к отображению файлов в память. Ввод/вывод с отображением в память реализуется при помощи системного вызова mmap. Вызов mmap работает со страницами памяти, и отображение файла в памяти будет выровнено по границе страницы. Вызов mmap определяется следующим образом:

Описание

uses linux;

type

tmmapargs=record

address : longint;

size : longint;

prot : longint;

flags : longint;

fd : longint;

offset : longint;

end;

Function MMap(const m:tmmapargs):longint;

Файл должен быть заранее открыт при помощи системного вызова fdopen. Полученный дескриптор файла используется в качестве поля fd в структуре tmmapargs.

Поле address позволяет программисту задать начало отображаемого файла в адресном пространстве процесса. Как и для вызова shmat, рассмотренного в разделе 8.3.4, в этом случае программе нужно знать расположение данных и кода процесса в памяти. Из соображений безопасности и переносимости лучше, конечно, позволить выбрать начальный адрес системе, и это можно сделать, присвоив параметру address значение 0. При этом возвращаемое вызовом mmap значение является адресом начала отображения. В случае ошибки вызов mmap вернет значение -1.

Поле offset определяет смещение в файле, с которого начинается отображение данных. Обычно нужно отображать в память весь файл, поэтому поле offset часто равно 0, что соответствует началу файла. Если поле offset не равно нулю, то оно должно быть кратно размеру страницы памяти.

Число отображаемых в память байтов файла задается полем size. Если это поле не кратно размеру страницы памяти, то size байтов будут взяты из файла, а оставшаяся часть страницы будет заполнена нулями.

Поле prot определяет, можно ли выполнять чтение, запись или выполнение содержимого адресного пространства отображения. Поле prot может быть комбинацией следующих значений, определенных в файле linux:

PROT_READ Разрешено выполнять чтение данных из памяти

PROT_WRITE Разрешено выполнять запись данных в память

PROT_EXEC Разрешено выполнение кода, содержащегося в памяти

PROT_NONE Доступ к памяти запрещен

Значение поля prot не должно противоречить режиму, в котором открыт файл.

Поле flags влияет на доступность изменений отображенных в память данных файла для просмотра другими процессами. Наиболее полезны следующие значения этого параметра:

MAP_SHARED

Все изменения в области памяти будут видны в других процессах, также отображающих файл в память, изменения также записываются в файл на диске

MAP_PRIVATE

Изменения в области памяти не видны в других процессах и не записываются в файл

После завершения процесса отображение файла автоматически отменяется. Чтобы отменить отображение файла в память до завершения программы, можно использовать системный вызов munmap.

Описание

uses linux;

function MUnMap(address:Pointer; length:Longint):Boolean;

Если был задан флаг MAP_SHARED, то в файл вносятся все оставшиеся изменения, при флаге MAP_PRIVATE все изменения отбрасываются.

Следует иметь в виду, что эта функция только отменяет отображение файла в память, но не закрывает файл. Файл требуется закрыть при помощи системного вызова fdсlose.

Следующий пример повторяет программу copyfile, последний вариант которой был рассмотрен в разделе 11.4. Эта программа открывает входной и выходной файлы и копирует один из них в другой. Для простоты опущена часть процедур обработки ошибок.

uses linux;

var

i, input, output, filesize:longint;

source, target:pchar;

args:tmmapargs;

const

endchar:char=#0;

type

oearray=array [0..0] of char;

poearray=^oearray;

begin

(* Проверка числа входных параметров *)

if paramcount <> 2 then

begin

writeln(stderr, 'Синтаксис: copyfile источник цель');

halt (1);

end;

(* Открыть входной и выходной файлы *)

input := fdopen (paramstr(1), Open_RDONLY);

if input = -1 then

begin

writeln(stderr, 'Ошибка при открытии файла ', paramstr(1));

halt (1);

end;

output := fdopen (paramstr(2), Open_RDWR or Open_CREAT or Open_TRUNC, octal(0666));

if output = -1 then

begin

fdclose (input);

writeln(stderr, 'Ошибка при открытии файла ', paramstr(2));

halt (2);

end;

(* Создать второй файл с тем же размером, что и первый. *)

filesize := fdseek (input, 0, SEEK_END);

fdseek (output, filesize - 1, SEEK_SET);

fdwrite (output, endchar, 1);

(* Отобразить в память входной и выходной файлы. *)

args.fd:=input;

args.flags:=MAP_SHARED;

args.prot:=PROT_READ;

args.size:=filesize;

args.address:=0;

args.offset:=0;

source:=pchar(mmap(args));

if longint(source) = -1 then

begin

writeln(stderr, 'Ошибка отображения файла 1 в память');

halt (1);

end;

args.fd:=output;

args.flags:=MAP_SHARED;

args.prot:=PROT_WRITE;

args.size:=filesize;

args.address:=0;

args.offset:=0;

target:=pchar(mmap(args));

if longint(target) = -1 then

begin

writeln(stderr, 'Ошибка отображения файла 2 в память');

halt (1);

end;

(* Копирование *)

for i:=0 to filesize-1 do

poearray(target)^[i] := poearray(source)^[i];

(* Отменить отображение обоих файлов *)

munmap (source, filesize);

munmap (target, filesize);

(* Закрыть оба файла *)

fdclose (input);

fdclose (output);

halt (0);

end.

Конечно, файлы были бы автоматически закрыты при завершении программы. Вызовы munmap включены для полноты изложения.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal