Альтернатива стандартному вводу/выводу является интерфейс представленный ядром ОС, который позволяет приложению отображать файл в память, то есть создавать соответствие один к одному между адресом в памяти и словом в файле. За счет такого механизма программа может обращаться файлу через память как к любым другим данным, находящимся в памяти.
Имеется механизм прозрачного отображения действий по отношению к данным в области памяти не данные, находящиеся в файле на диске:
#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 занимает целое число страниц, в памяти оно не должно выходить за пределы адресного пространства процесса, а манипулирование отображения в памяти требует определенной затраты ядра ОС.