Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 [ 104 ] 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

12.2. Функции mmap, munmap и msync

Функция mmap отображает в адресное пространство процесса файл или объект разделяемой памяти Posix. Мы используем эту функцию в следующих ситуациях:

1. С обычными файлами для обеспечения ввода-вывода через отображение в память (раздел 12.3).

2. Со специальными файлами для обеспечения неименованного отображения памяти (разделы 12.4 и 12.5).

3. С shm open для создания участка разделяемой неродственными процессами памяти Posix.

finclude <sys/nrian.h>

void *mmap(void *addr. size t len. int prot. int flags, int fd. off t offset); /* Возвращает начальный адрес участка памяти в случае успешного завершения, MAP FAILED - в случае ошибки */

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

Аргумент len задает длину отображаемого участка в байтах; участок может начинаться не с начала файла (или другого объекта), а с некоторого места, задаваемого аргументом offset. Обычно offset = 0. На рис. 12.5 изображена схема отображения объекта в память.

верхняя область памяти

значение, возвращаемое -mmap

нижняя область памяти

адресное пространство процесса

отображенный в память файл

файл, задаваемый дескриптором fd:

Рис. 12.5. Пример отображения файла в память

отсраженная в память

область файла

Защита участка памяти с отображенным объектом обеспечивается с помощью аргумента prot и констант, приведенных в табл. 12.1. Обычное значение этого аргумента - PROT READ I PROT WRITE, что обеспечивает доступ на чтение и запись.



Таблица 12.1.

Аргумент prot дпя вызова mmap

prot

Описание

PROT READ PROT WRITE PROT EXEC PROT NONE

Данные могут быть считаны Данные могут быть записаны Данные могут быть выполнены Доступ к данным закрыт

Таблица 12.2. Аргумент flag дпя вызова mmap

flag

Описание

MAP SHARED MAP PRIVATE

MAP FIXED

Изменения передаются другим процессам Изменения не передаются другим процессам и не влияют на отображенный объект Аргумент addr интерпретируется как адрес памяти

Аргумент flags может принимать значения из табл. 12.2. Можно указать только один из флагов - MAP SHARED или MAP PRIVATE, прибавив к нему при необходимости MAP FIXED. Если указан флаг MAP PRI VATE, все изменения будут производиться только с образом объекта в адресном пространстве процесса; другим процессам они доступны не будут. Если же указан флаг MAP SHARED, изменения отображаемых данных видны всем процессам, совместно использующим объект.

Для обеспечения переносимости программ флаг MAP FIXED указывать не следует. Если он не указан, но аргумент addr представляет собой ненулевой указатель, интерпретация этого аргумента зависит от реализации. Ненулевое значение аб?й?г обычно трактуется как указатель на желаемую область памяти, в которую нужно произвести отображение. В переносимой программе значение addr должно быть нулевым и флаг MAP FIXED не должен быть указан.

Одним из способов добиться совместного использования памяти родительским и дочерним процессами является вызов mmap с флагом MAP SHARED перед вызовом fork. Стандарт Posix.l гарантирует в этом случае, что все отображения памяти, установленные родительским процессом, будут унаследованы дочерним. Более того, изменения в содержимом объекта, вносимые родительским процессом, будут видны дочернему, и наоборот. Эту схему мы вскоре продемонстрируем в действии.

Для отключения отображения объекта в адресное пространство процесса используется вызов munmap:

finclude <sys/nrian.h>

int munmapCvoid *addr. size t /en):

/* Возвращает 0 в случае успешного завершения, -1 - в случае ошибки */ Аргумент addr должен содержать адрес, возвращенный mmap, а len - длину области отображения. После вызова munmap любые попытки обратиться к этой области памяти приведут к отправке процессу сигнала SIGSEGV (предполагается, что эта область памяти не будет снова отображена вызовом mmap).

Если область была отображена с флагом MAP PRIVATE, все внесенные за время работы процесса изменения сбрасываются.



В изображенной на рис. 12.5 схеме ядро обеспечивает синхронизацию содержимого файла, отображенного в память, с самой памятью при помощи алгоритма работы с виртуальной памятью (если сегмент был отображен с флагом MAP SHARED). Если мы изменяем содержимое ячейки памяти, в которую отображен файл, через некоторое время содержимое файла будет соответствующим образом изменено ядром. Однако в некоторых случаях нам нужно, чтобы содержимое файла всегда было в соответствии с содержимым памяти. Тогда для осуществления моментальной синхронизации мы вызываем msync:

finclude <sys/nrian.h>

int ttisyncCvoid *addr. size t len. int flags):

/* Возвращает 0 в случае успешного завершения. -1 - в случае ошибки */ Аргумент flags представляет собой комбинацию констант из табл. 12.3.

Таблица 12.3. Значения аргумента flags для функции msync

Константа

Описание

MS ASYNC

Осуществлять асинхронную запись

MS SYNC

Осуществлять синхронную запись

MS INVALIDATE

Сбросить кэш

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

Почему вообще используется отображение в память?

До сих пор мы всегда говорили об отображении в память содержимого файла, который сначала открывается вызовом open, а затем отображается вызовом mmap. Удобство состоит в том, что все операции ввода-вывода осуществляются ядром и скрыты от программиста, а он просто пишет код, считывающий и записывающий данные в некоторую область памяти. Ему не приходится вызывать read, wri te или 1 seek. Часто это заметно упрощает код.

ПРИМЕЧАНИЕ -

Вспомните нашу реализацию очередей сообщений Posix с использованием mmap, где значения сохранялись в структуре msg lidr и считывались из нее же (листинги 5.26 и 5.28).

Следует, однако, иметь в виду, что не все файлы могут быть отображены в память. Попытка отобразить дескриптор, указывающий на терминал или сокет, приведет к возвращению ошибки при вызове mmap. К дескрипторам этих типов доступ осуществляется только с помощью read и write (и аналогичных вызовов).

Другой целью использования mmap может являться разделение памяти между неродственными процессами. В этом случае содержимое файла становится



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 [ 104 ] 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.