КАТЕГОРИИ:
АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
Отображение файлов в виртуальное адресное пространство. Разделяемая память.В OC Unix процесс имеет возможность отобразить участки файла в собственное адресное пространство. Далее с данными в файле можно работать как с обычными переменными. Фактически этот механизм является альтернативой механизму read/write. Отображение осуществляется с помощью mmap: #include <sys/types.h> #include <sys/mman.h> Caddr_t //соответствует void* - безтиповый указатель. Caddr_t mmap(caddr_t addr,int len,int prot,int flags,int fd,int offset); Этот вызов задает отображение len байт в файл с дискриптором fd начиная с позиции offset со стартовым адресом addr. Параметр prot определяет права доступа к области памяти, которые должны соответствовать правам доступа к файлу. Права доступа к fd указываются предварительно в open. До использования mmap файл fd должен быть открыт. Prot_READ – только для чтения Prot_WRITE – только для записи Prot_EXEC – доступен для исполнения Prot_NONE – область недоступна С помощью логического ИЛИ (|) можно объединять условия. Наличие EXEC говорит о возможности передачи управления в область отражения. Такой подход ипользуется при загрузки динамических библиотек, когда библиотека отображается в адресное пространство процесса. Параметр flags задает дополнительные механизмы отображения: MAP_SHARED – область памяти может совместно использоваться несколькими процессами MAP_PRIVATE – используется только вызывающим процессом MAP_FIXED – требует выделения памяти точно начиная с addr. Можно через логическое ИЛИ добавлять к флагам опции. Например MAP_ANONYMOUS. Эта опция позволяет создать просто область памяти, без файла fd, и offset игнорируется в этом случае. Если память выделена, то mmap с параметром ANONYMOUS отличается от обычной тем, что при копировании процесса вызовом fork(), эта память не копируется, а становится доступной для обоих процессов. Значение параметра addr обычно задается равным NULL. Тогда ОС сама выбирает свободную область виртуального адресного пространства. В случае ошибки mmap возвращает значение (-1), преобразованное в void*, т.е. будет иметь вид MAP_FAILED. Отображение автоматически снимается при завершении процесса. Процесс может явно снять отображение с помощью системного вызова int munmap(void* addr,int len); Закрытие файла не приведет к снятию отображения. Снятие отображения не влияет немедленно на файл. Обновление файла производится ядром согласно механизму управления виртуальной памятью. msync() – позволяет синхронизировать обновление страниц в памяти с вторичной памятью. При выполнении mmap OC округляет len до следующей страницы виртуальной памяти. Например размер файла 96 байт, а размер страницы 4096 байт, то 96 байт займут данные файла, а 4к байт будет заполнено нулями, но процесс сможет модифицировать эти 4кб. На содержимом файла это не отбразится. Процесс не может изменить размер файла. Пример 1: #include <sys/types.h> #include <sys/mman.h> main() {int fd; char*ptr; fd=Open(“f1.at”,O_RDWR); if (fd==-1){perror(“ошибка open”);exit(1);} ptr=(char*) mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if (ptr==MAP_FAILED){perror(“ошибка mmap”);exit(2);} ………. После успешного вызова mmap выражение ptr[25], будет равно значению 26ого байта из файла. Операция ptr[26]=”a” занесет в 26ой байт символ “a”. Пример 2: #include <sys/types.h> #include <sys/mman.h> main() {int* ptr; ptr=(char*)mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,0,0); if (ptr== FAILED){perror(“ошибка mmap”);exit(1);} if fork()==0) then {//дочерний процесс//} else {//родительский процесс//} В примере родительский и дочерний процессы имеют доступ к массиву целых чисел размером по 4 байта. Массив доступен через ptr. Пример 3: Упрощенная версия копирования файлов – cp. #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> main(int argC,char* argV[]) {int fd1,fd2;caddr_t addr1(исходный),addr2(целевой); struct stat filestat;//тип stat для структуры filestat содержит метаданные из файлового дискриптора. fd1=open(argV[1],O_RDONLY); fd2=open(argV[2],O_WRONLY); fstat(fd1,&filestat);//определяем размер исходного файла lseek(fd2,filestat.st_size-1,SEEK_SET);//делаем размер целевого файла равным исходному write(fd2,””,1); addr1=mmap(NULL,filestat.st_size,PROT_READ|PROT_WRITE,fd1,0); addr2=mmap(NULL,filestat.st_size,PROT_READ|PROT_WRITE,fd2,0); memcpy(addr2,addr1,filestat.st_size); exit(0);}
|