Файлы, отображающиеся в памяти

Альтернатива стандартному вводу/выводу является интерфейс представленный ядром ОС, который позволяет приложению отображать файл в память, то есть создавать соответствие один к одному между адресом в памяти и словом в файле. За счет такого механизма программа может обращаться файлу через память как к любым другим данным, находящимся в памяти.

Имеется механизм прозрачного отображения действий по отношению к данным в области памяти не данные, находящиеся в файле на диске:

#include <sys/mman.h>

void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

Этот системный вызов запрашивает у ядра ОС разрешение на отображение этих len байтов из файла fd, начиная со смещения в файле offset. Разрешение на доступ отображает параметр prot, а допустимые возможности определяет flags.

Далее представлены возможные значения prot:

PROT_READ, страница доступна для считывания

PROT_WRITE, страница доступна для записи

PROT_EXEC, страница доступна для выполнения

PROT_NONE, доступ к странице запрещен

Допустимые варианты flags:

MAP_FIXED, позволяет считать первый параметр, а если ядро не может разместить данные по указанному адресу, то выводит сообщение об ошибке

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

MAP_SHAKE, действие видны для остальных процессов и отображаются на физических файлах

Первый же параметр addr служит для того, чтобы определять место в ОП, куда лучше всего отображать данные в файл. Если в качестве данного параметра представлено значение NULL (или 0), то ОС сама выбирает, куда отображать данные.

void *p;

...

p=mmap(0,len,PROT_READ,MAP_SHADER,fd,0);

Возвращает системный вызов фактический адрес в памяти, куда будет производиться отображение.

Отображение ведется по страницам. Страница – это наименьшая единица памяти, которая может обладать собственным разрешением и поведением. Отображения области памяти должны быть кратны размеру страницы, и оба параметра addr и offset должны быть выровнены на границе страницы.

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

Для того, чтобы узнать размер страницы:

#include <unistd.h>

long sysconf(int name);

long page_size=sysconf(_SC_PAGESIZE);

В случае успешного завершения функции mmap возвращается адрес отображения в памяти, а в случае ошибки значение MAP_FAILED и устанавливает значения errno:

EACCESS – файл, указанный при помощи файлового дескриптора fd, не является обычным файлом или же режим, в котором открыт файл, конфликтует со значением prot или flags

EAGAIN – файл заблокирован

EBADF – значение fd не является допустимым

EINVAL – один или несколько параметров имеют недопустимое значение

ENFILE – достигнуто максимальное количество открытых файлов

ENODEV – используемая файловая система не поддерживает отображение в память

ENOMEM – у процесса недостаточно памяти

EOVERFLOW – выход за пределы адресного пространства

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fentl.h>

#include <unistd.h>

#include <sys/mman.h>

int main(int argc,char *argv[]) {

struct stat sb;

off_t len;

char *p;

int fd;

if (argc<2) //проверяет корректность вызова

{ printf(“Ошибка вызова программы \n”);

return(1); }

fd=open(argv[1],O_RDONLY); //открытие файла

if (fd==-1)

{ perror(“open”);

return(1); }

if (fstat(fd,&sb)==-1)

{ perror(“fstat”);

return(1); }

if (!S_ISREG(sb.st_mode))

{ prinf(“Это %s не файл \n”,argv[1]);

return(1); }

p=mmap(0,sb.st_size,PROT_READ,MAP_SHARED,fd,0); //отображение

в память, второй параметр указывает на размер файла

if (p==MAP_FAILED) //ошибка

{ perror(“mmap”);

return(1); }

if (close(fd)==-1) //закрытие fd

{ perror(“close”);

return(1); }

for (len=0; len<sb.st_size; len++)

putchr(p[len]); //байты из области p

if (munmap(p,sb.st_size)==-1) //закрытие области отображения,

указывается адрес начала и размер области

{ perror(“munmap”);

return(1); }

}

Программа принимает в качестве аргумента имя текстового файла и выводит содержимое этого файла на экран дисплея.

Достоинствами системного вызова mmap можно назвать то, что при его использовании не требуется дополнительное копирования, выполняемое при вызове read и write, что процесс выполнения действий достигается путем прямой работы с ОП, что для поиска необходимых данных в отображении необходимо просто манипулировать указателем, а действия по позиционированию производить не требуется. Но отображение системного вызова mmap занимает целое число страниц, в памяти оно не должно выходить за пределы адресного пространства процесса, а манипулирование отображения в памяти требует определенной затраты ядра ОС.




Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: