10  fd = Open(FILE, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);

11  ptr = Mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

12  for (i = 4096; i = SIZE; i += 4096) {

13   printf("setting file size to %d\n", i);

14   Ftruncate(fd, i);

15   printf("ptr[%d] = %d\n", i-1, ptr[i-1]);

16  }

17  exit(0);

18 }

Открытие файла

9-11 Мы создаем файл, если он еще не существует, или урезаем его до нулевой длины, если он существует. Затем файл отображается в область объемом 32 768 байт, хотя его текущий размер равен нулю.

Увеличение размера файла

12-16 Мы увеличиваем размер файла на 4096 байт за один вызов ftruncate (раздел 13.3) и считываем из него последний байт в каждом проходе цикла.

Запустив эту программу, мы убедимся в возможности обращаться к новым данным по мере роста файла:

alpha % ls –l test.data

test.data: No such file or directory

alpha % test2

setting file size to 4096

ptr[4095] = 0

setting file size to 8192

ptr[8191] = 0

setting file size to 12288

ptr[12287] = 0

setting file size to 16384

ptr[16383] = 0

setting file size to 20480

ptr[20479] = 0

setting file size to 24576

ptr[24575] = 0

setting file size to 28672

ptr[28671] = 0

setting file size to 32768

ptr[32767] = 0

alpha % ls-l test.data

-rw-r--r-- 1 rstevens other1 32768 Mar 20 17:53 test.data

Этот пример показывает, что ядро всегда следит за размером отображаемого в память объекта (в данном примере это файл test.data), и мы всегда имеем возможность обратиться к байтам, лежащим внутри области, ограниченной размером файла и размером отображения. Те же результаты получаются при запуске этой программы в Solaris 2.6.

В этом разделе мы работали с отображением файлов в память с помощью mmap. В упражнении 13.1 нам придется немного изменить две наших программы для работы с разделяемой памятью Posix, и мы получим те же результаты.

<p>12.7. Резюме</p>

Разделяемая память представляет собой самую быстродействующую форму IPC, потому что данные из разделяемой области памяти доступны всем потокам и процессам, с ней работающим. Обычно для координации совместных действий потоков и процессов, использующих разделяемую память, требуется некоторая форма синхронизации.

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

Если необходимо совместное использование области памяти после вызова fork, можно упростить решение этой задачи, используя неименованное отображение в память. Для этого в ядрах Berkeley при вызове mmap указывается флаг MAP_ANON, а в ядрах SVR4 производится отображение специального файла /dev/zero.

Причина, по которой мы столь детально разобрали работу mmap, заключается в том, что отображение файлов в память часто оказывается очень полезным, а также в том, что mmap используется для работы с разделяемой памятью Posix, которая является предметом изучения следующей главы.

Для работы с памятью стандартом Posix определено еще четыре функции:

■ mlockall делает всю память процесса резидентной; munlockall снимает эту блокировку;

■ mlock делает определенный диапазон адресов процесса резидентным. Аргументами функции являются начальный адрес и длина области. Функция munlock разблокирует указываемую область памяти.

<p>Упражнения</p>

1. Что произойдет с программой в листинге 12.7, если добавить еще один повтор цикла for?

2. Предположим, что имеются два процесса, один из которых отправляет сообщения другому. Для этого используются очереди сообщений System V. Нарисуйте схему передачи сообщений от отправителя к получателю. Теперь представьте, что используется реализация очередей сообщений Posix из раздела 5.8, и нарисуйте аналогичную схему.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже