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

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.5 (продолжение)

9 if (argc != 2)

10 err quit( usage: incr dev zero <#loops> );

11 nloop = atoi(argv[l]):

12 /* открываем /dev/zero и отображаем в память */

13 fd - Open( /dev/zero , 0 RDWR);

14 ptr =Mmap(NULL, sizeof(int), PROT REAO PROT WRITE, MAP SHAREO, fd, 0):

15 Close(fd);

6-11 Автоматическая переменная zero больше не используется, как и аргумент командной строки, задававший имя создаваемого файла. 12-15 Мы открываем файл /dev/zero и передаем его дескриптор функции mmap. Область памяти будет гарантированно проинициализирована нулями.

12.6. Обращение к объектам, отображенным в память

Когда в память отображается обычный файл, размер полученной области (второй аргумент вызова mmap), как правило, совпадает с размером файла. Например, в листинге 12.3 размер файла устанавливается равным размеру структуры shared вызовом write и это же значение размера области используется при отображении его в память. Однако эти два параметра - размер файла и размер области памяти, в которую он отображен, - могут и отличаться.

Для детального изучения особенностей функции mmap воспользуемся программой в листинге 12.6.

Листинг 12.6. Отображение файла: размер файла совпадает с размером области памяти

shtti/testl.c

1 finclude unpipc.h

2 int

3 ttiain(int argc, char **argv)

5 int fd, i;

6 char *ptr:

7 size t filesize, mmapsize. pagesize:

8 if (argc != 4)

9 err quit( usage: testl <pathnanie> <filesize> <mmapsize> );

10 filesize = atoi(argv[2]):

11 mmapsize = atoi(argv[3]):

12 /* открытие файла, установка его размера */

13 fd = Open(argv[l], 0 ROWR 0 CREAT OJRUNC. FILE M(X)E):

14 Lseek(fd, filesize-1. SEEK SET):

15 Write(fd, , 1);

16 ptr Mmap(NULL. mmapsize. PROT READ PROT WRITE, MAP SHAREO, fd. 0);

17 Close(fd);

18 pagesize - Sysconf( SC PAGESIZE):

19 printf( PAGESIZE - ld\n . (long) pagesize);



20 for (i = 0; i < ttiaxCfilesize. mmapsize); i += pagesize) {

21 printf( ptr[d] = d\n . i. ptr[i]);

22 ptr[i] = 1:

23 printf( ptr[ d] d\n . i + pagesize - 1. ptr[i + pagesize - 1]):

24 ptr[i + pagesize - 1] = 1;

25 }

26 printf( ptr[ d] = d\n , i, ptr[i]):

27 exitCO);

28 }

Аргументы командной строки

8-11 Аргументы командной строки задают полное имя создаваемого и отображаемого в память файла, его размер и размер области памяти.

Создание, открытие, урезание файла; установка его размера

12-15 Если файл не существует, он будет создан. Если он существует, его длина будет установлена равной нулю. Затем размер файла устанавливается равным указанному размеру путем вызова 1 seek для установки текущей позиции, равной требуемому размеру минус 1 и записи 1 байта.

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

16-17 Файл отображается в память, причем размер области задается последним аргументом командной строки. Затем дескриптор файла закрывается.

Вывод размера страницы памяти

18-19 Размер страницы памяти получается вызовом sysconf и выводится на экран.

Чтение и запись в область отображения

20-26 Считываются и выводятся данные из области памяти, в которую отображен файл. Считываются первый и последний байты каждой страницы этой области памяти. Все значения должны быть нулевыми. Затем первый и последний байты каждой страницы устанавливаются в 1. Одно из обращений к памяти может привести к отправке сигнала процессу, что приведет к его заверщению. После заверщения цикла for мы добавляем еще одно обращение к следующей странице памяти, что должно заведомо привести к ошибке и заверщению программы (если ошибка не возникла раньше).

Рассмотрим первую ситуацию: размер файла совпадает с размером области памяти, но эта величина не кратна размеру страницы памяти в данной реализации:

Solaris % Is -1 foo

foo: No such file or directory

Solaris % testl foo 5000 5000

PAGESIZE = 4096

ptr[0] = 0

ptr[4095] = 0

ptr [4096] = 0



ptr [8191] = О Segmentation Fault(coredump) Solaris % Is -1 foo

-rw-r--r-- 1 rstevens otherl 5000 Mar 20 17:18 foo

Solaris od -b -A d foo

0000000 001 ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО

0000016 ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО *

0004080 ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО 001

0004096 001 ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО

0004112 ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО ООО *

0005000

Размер страницы памяти составляет 4096 байт, и мы смогли обратиться ко всему содержимому второй страницы (индексы 4096-8191), но обращение к третьей странице (8192) приводит к отправке сигнала SIGSEGV, о чем интерпретатор оповещает сообщением Segmentation Fault. Хотя мы и установили значение ptr[8191] = 1, оно не было записано в файл и его размер остался равным 5000 байт. Ядро позволяет считывать и записывать данные в ту часть последней страницы, которая не относится к отображенному файлу (поскольку защита памяти осуществляется ядром постранично), но изменения в этой области памяти не будут скопированы в файл. А вот относящиеся к файлу изменения (индексы 0,4095 и 4096) были скопированы в него, в чем мы убедились, воспользовавшись программой od (параметр -Ь при вызове последней указывает на необходимость выводить значения байтов в восьмеричном формате, а параметр -А d позволяет выводить адреса в десятичном формате). На рис. 12.8 изображена схема памяти для данного примера.

размер файла


сдвиг: О 4999

индекс: О 4999 5000 8191

остаток I

область отображения послодней

гярашш \ обращение приводит

к этой области можно обращаться-SIGSV

размер, указываемый при вызове mmap Рис. 12.8. Размер отображаемого файла совпадает с размером области памяти

Запустив этот пример в Digital Unix 4.0В, получим тот же результат, но размер страницы памяти в этой системе равняется 8192 байт:

alpha Is -1 foo foo not found

alpha % testl foo 5000 5000



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.
Копирование материалов разрешено исключительно при условии цититирования.