Главная страница Взаимодействие нетривиальных процессов сдвиг: О индекс: О размер файла файл 4999 4999 5000 8191 8192 размер, указываемый при вызове mmap 14999 остаток I последней I - к этой области можно обращаться - обращение приводит к отправке SIGSEGV обращение приводит к отправке SIGSEGV Рис. 12.9. Размер области памяти больше размера отображаемого файла PAGESIZE 8192 ptr[0] = О ptr[8191] = О Мегпогу fault (coreduttip) alpha Is -1 foo -rw-r--r-- 1 rstevens operator 5000 Mar 21 08:40 foo Мы все так же можем обратиться к памяти за пределами отображенного файла, но не выходя за границы страницы памяти (индексы с 5000 по 8191). Обращение к ptr[8192] приводит к отправке SIGSEGV, на что мы и рассчитывали. Вторая ситуация: размер области памяти (15 ООО байт) превышает размер файла (5000 байт): Solaris % т foo Solaris % testl foo 5000 15000 ptr[0] = 0 ptr[4095] = 0 ptr[4096] = 0 ptr[8191] = 0 Bus Error(coreduttip) Solaris % Is -1 foo -rw-r--r-- 1 rstevens otherl 5000 Mar 20 17:37 foo Полученный результат аналогичен результату предыдущего примера, в котором размер файла равнялся размеру области отображения (5000 байт). Однако в данном примере генерируется сигнал SIGBUS (о чем интерпретатор оповещает сообщением Bus Error), тогда как в предыдущем примере отправлялся сигнал SIGSEGV. Отличие в том, что SIGBUS означает выход за границы отображенного файла внутри области отображения, а SIGSEGV - выход за границы области. Этим примером мы показали, что ядро хранит информацию о размере отображенного объекта, даже несмотря на то, что его дескриптор закрыт. Ядро позволяет указать при вызове mmap размер области памяти, больший размера файла, но не позволяет обратиться к адресам в этой области (кроме остатка последней страницы, в которой еще имеется содержимое собственно файла - индексы с 5000 по 8191 в данном случае). На рис. 12.9 приведена иллюстрация к этому примеру. Следующая программа приведена в листинге 12.7. Ею мы иллюстрируем типичные методы работы с увеличивающимися в размерах файлами: при отображении в память заказывается большой размер области, текущий размер файла учитывается при всех операциях (чтобы не выйти за его пределы в памяти), а затем он просто увеличивается, по мере того как в файл записываются данные. Листинг 12.7. Отображение увеличивающегося файла в память shtti/test2.c 1 finclude unpipc.h 2 fdefine FILE test.data 3 fdefine SIZE 32768 4 int 5 maindnt argc. char **argv) 7 int fd. i: 8 char *ptr; 9 /* открытие, создание, урезание и установка размера файла, вызов гшар */ 10 fd = Open (FILE. 0 RDWR 0 CREAT OJRUNC. FILE MODE): 11 ptr = Mmap(NULL. SIZE. PROTJEAD PROTJRITE. MAPJHARED, 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] = %й\п , i-1, ptr[i-l]): 16 } 17 exit(O): 18 } Открытие файла 9-11 Мы создаем файл, если он еще не существует, или урезаем его до нулевой длины, если он существует. Затем файл отображается в область объемом 32 768 байт, хотя его текущий размер равен нулю. Увеличение размера файла 12-16 Мы увеличиваем размер файла на 4096 байт за один вызов ftruncate (раздел 13.3) и считываем из него последний байт в каждом проходе цикла. Запустив эту программу, мы убедимся в возможности обращаться к новым данным по мере роста файла: alpha Is -1 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 163B4 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 % Is -1 test.data -m-r-r-- 1 rstevens otherl 32768 Mar 20 17:53 test.data Этот пример показывает, что ядро всегда следит за размером отображаемого в память объекта (в данном примере это файл test .data), и мы всегда имеем возможность обратиться к байтам, лежащим внутри области, ограниченной размером файла и размером отображения. Те же результаты получаются при запуске этой программы в Solaris 2.6. В этом разделе мы работали с отображением файлов в память с помощью mmap. в упражнении 13.1 нам придется немного изменить две нащих программы для работы с разделяемой памятью Posix, и мы получим те же результаты. 12.7. Резюме Разделяемая память представляет собой самую быстродействующую форму IPC, потому что данные из разделяемой области памяти доступны всем потокам и процессам, с ней работающим. Обычно для координации совместных действий потоков и процессов, использующих разделяемую память, требуется некоторая форма синхронизации. В этой главе мы подробно рассмотрели свойства функции mmap и отображение обычных файлов в память, потому что это один из способов обеспечения взаимодействия между неродственными процессами. После отображения файла в память для обращения к нему больше не нужно использовать вызовы read, write и 1 seek - вместо этого можно напрямую работать с ячейками памяти, относящимися к той области, указатель на которую возвращает mmap. Замена явных операций с файлом на обращение к ячейкам памяти может упростить программу и в некоторых случаях увеличить быстродействие. Если необходимо совместное использование области памяти после вызова fork, можно упростить рещение этой задачи, используя неименованное отображение в память. Для этого в ядрах Berkeley при вызове mmap указывается флаг MAP ANON, а в ядрах SVR4 производится отображение специального файла /dev/zero. Причина, по которой мы столь детально разобрали работу mmap, заключается в том, что отображение файлов в память часто оказывается очень полезным, а также в том, что mmap используется для работы с разделяемой памятью Posix, которая является предметом изучения следующей главы. Для работы с памятью стандартом Posix определено еще четыре функции: ш ml ockal 1 делает всю память процесса резидентной; muni ockal 1 снимает эту блокировку; ml оск делает определенный диапазон адресов процесса резидентным. Аргументами функции являются начальный адрес и длина области. Функция muni оск разблокирует указываемую область памяти.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |