Совместно используемая память (англ. Shared memory) является самым быстрым средством обмена данными между процессами[1].
В других средствах межпроцессового взаимодействия (IPC) обмен информацией между процессами проходит через ядро, что приводит к переключению контекста между процессом и ядром, т.е. к потерям производительности[2].
Техника совместно используемой памяти позволяет осуществлять обмен информацией через общий для процессов сегмент памяти без использования системных вызовов ядра. Сегмент совместно используемой памяти подключается в свободную часть виртуального адресного пространства процесса[3]. Таким образом, два разных процесса могут иметь разные адреса одной и той же ячейки, подключенной совместно используемой памяти.
Краткое описание работы
правитьПосле создания совместно используемого сегмента памяти любой из пользовательских процессов может подсоединить его к своему собственному виртуальному пространству и работать с ним как с обычным сегментом памяти. Недостатком такого обмена информацией является отсутствие каких бы то ни было средств синхронизации, однако для преодоления этого недостатка можно использовать технику семафоров.
Реализация технологии «клиент—сервер»
правитьВ схеме обмена данными между двумя процессами — (клиентом и сервером), использующими совместно используемую память, — должна функционировать группа из двух семафоров. Первый семафор служит для блокирования доступа к совместно используемой памяти, его разрешающий сигнал — 1, а запрещающий — 0. Второй семафор служит для сигнализации сервера о том, что клиент начал работу, при этом доступ к совместно используемой памяти блокируется, и клиент читает данные из памяти. Теперь при вызове операции сервером его работа будет приостановлена до освобождения памяти клиентом.
Сценарий использования совместно используемой памяти
править- Сервер получает доступ к совместно используемой памяти, используя семафор.
- Сервер производит запись данных в совместно используемой память.
- После завершения записи данных сервер освобождает доступ к совместно используемой памяти с помощью семафора.
- Клиент получает доступ к совместно используемой памяти, запирая доступ к этой памяти для других процессов с помощью семафора.
- Клиент производит чтение данных из совместно используемой памяти, а затем освобождает доступ к памяти с помощью семафора.
Программная реализация
правитьВ программном обеспечении совместно используемой памятью называют:
- Метод межпроцессного взаимодействия (IPC), то есть способ обмена данными между программами, работающими одновременно. Один процесс создаёт область в оперативной памяти, которая может быть доступна для других процессов.
- Метод экономии памяти, путём прямого обращения к тем исходным данным, которые при обычном подходе являются отдельными копиями исходных данных, вместо отображения виртуальной памяти или описанного метода . Такой подход обычно используется для совместно используемых библиотек и для XIP.
Поскольку оба процесса могут получить доступ к общей области памяти как к обычной памяти, это очень быстрый способ связи (в отличие от других механизмов IPC, таких как именованные каналы, UNIX-сокеты или CORBA). С другой стороны, такой способ менее гибкий, например, обменивающиеся процессы должны быть запущены на одной машине (из перечисленных методов IPC только сетевые сокеты, не путать с сокетами домена UNIX, могут вести обмен данными через сеть), и необходимо быть внимательным, чтобы избежать проблем при использовании совместно используемой памяти на разных ядрах процессора и аппаратной архитектуре без когерентного кэша.
Обмен данными через совместно используемую память используется, например, для передачи изображений между приложением и X-сервером на Unix-системах или внутри объекта IStream возвращаемого CoMarshalInterThreadInterfaceInStream в библиотеке COM под Windows.
Динамические библиотеки, как правило, загружаются в память один раз и отображены на несколько процессов, и только страницы, которые специфичны для отдельного процесса (поскольку отличаются некоторые идентификаторы) дублируются, как правило, с помощью механизма, известного как копирование-при-записи, который при попытке записи в совместно используемую память незаметно для вызывающего запись процесса копирует страницы памяти, а затем записывает данные в эту копию.
В UNIX-подобных операционных системах
правитьPOSIX предоставляет стандартизированное API для работы с совместно используемой памятью — POSIX Shared Memory. Одной из ключевых особенностей операционных систем семейства UNIX является механизм копирования процессов (системный вызов fork()
), который позволяет создавать анонимные участки совместно используемой памяти перед копированием процесса и наследовать их процессами-потомками. После копирования процесса совместно используемой память будет доступна как родительскому, так и дочернему процессу.[3][4]
Существует два разных подхода к подключению и использованию совместно используемой памяти:
- в стиле UNIX System V, используя функции расширения POSIX:XSI (часть стандарта POSIX.1-2001)
shmget
,shmctl
,shmat
иshmdt
[5]; - через функции POSIX
shm_open
,shm_unlink
,ftruncate
иmmap
(стандарт POSIX.1-2001)[6].
Совместно используемая память в стиле UNIX System V
правитьUNIX System V предоставляет набор функций языка C, позволяющий работать с совместно используемой памятью[7]:
shmget
— создание сегмента совместно используемой памяти с привязкой к целочисленному идентификатору, либо анонимного сегмента совместно используемой памяти (при указании вместо идентификатора значения IPC_PRIVATE)[8];shmctl
— установка параметров сегмента памяти[9];shmat
— подключение сегмента к адресному пространству процесса[4];shmdt
— отключение сегмента от адресного пространства процесса[10].
Именованная совместно используемая память подразумевает ассоциацию с каждым участком памяти уникального числового ключа в рамках операционной системы, по которому в дальнейшем можно подключить совместно используемой память в другом процессе.[8]
POSIX позволяет связать с объектом совместно используемой памяти файловый дескриптор, что является более унифицированным механизмом, чем механизм UNIX System V. Для работы с памятью могут быть использованы следующие функции языка C:
shm_open
— создание или подключение объекта совместно используемой памяти POSIX по его имени[6];shm_unlink
— удаление объекта совместно используемой памяти по его имени (при этом сегмент совместно используемой памяти будет существовать, пока не будет отключен от всех процессов)[11];ftruncate
— задаёт или изменяет размер совместно используемой памяти (или отображённого в память файла)[12];mmap
— подключает существующий или создаёт анонимный сегмент совместно используемой памяти к адресному пространству процесса[3].
В операционной системе Windows для создания совместно используемой памяти используются функции CreateFileMapping
и MapViewOfFile
[13] из MSDN.
Поддержка в языках программирования
правитьНекоторые библиотеки языка C++ предлагают доступ к работе с совместно используемой памятью в кроссплатформенном виде. Например, библиотека Boost предоставляет класс boost::interprocess::shared_memory_object
[14] для POSIX-совместимых операционных систем, а библиотека Qt предоставляет класс QSharedMemory
, унифицирующий доступ к совместно используемой памяти для разных операционных систем с некоторыми ограничениями[15].
В Java 7 под операционной системой GNU/Linux совместно используемой память может быть реализована отображением файла из каталога /dev/shm/
(либо /run/shm/
, в зависимости от дистрибутива) в память[16] с помощью метода map
класса java.nio.MappedByteBuffer
[17].
Поддержка совместно используемой памяти осуществлена во многих других языках программирования. Так, PHP предоставляет API[18] для создания совместно используемой памяти, чьи функции схожи с функциями POSIX.
См. также
правитьПримечания
править- ↑ Колисниченко Денис Николаевич. Разработка Linux-приложений. — БХВ-Петербург, 2012-01-01. — 430 с. — ISBN 9785977507479. Архивировано 23 июля 2016 года.
- ↑ Hyok-Sung Choi, Hee-Chul Yun. Context Switching and IPC Performance Comparison between uClinux and Linux on the ARM9 based Processor (англ.) // Samsung Electronics : Технический отчёт. — 2004. Архивировано 6 марта 2016 года.
- ↑ 1 2 3 mmap . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 6 декабря 2015 года.
- ↑ 1 2 shmat . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 30 декабря 2015 года.
- ↑ System Interfaces Chapter 2 . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 8 января 2016 года.
- ↑ 1 2 shm_open . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 21 ноября 2015 года.
- ↑ Kay A. Robbins. UNIX systems programming: communication, concurrency, and threads. — Prentice Hall PTR, 2003. — С. 512. Архивировано 22 сентября 2014 года.
- ↑ 1 2 shmget . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 5 марта 2016 года.
- ↑ shmctl . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 7 декабря 2015 года.
- ↑ shmdt . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 12 декабря 2015 года.
- ↑ shm_unlink . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 9 ноября 2015 года.
- ↑ ftruncate . pubs.opengroup.org. Дата обращения: 3 января 2016. Архивировано 1 февраля 2016 года.
- ↑ Creating Named Shared Memory . Дата обращения: 26 июня 2014. Архивировано 5 июня 2014 года.
- ↑ Sharing memory between processes - 1.60.0 . www.boost.org. Дата обращения: 4 января 2016. Архивировано 29 декабря 2015 года.
- ↑ QSharedMemory Class | Qt Core 5.5 . doc.qt.io. Дата обращения: 4 января 2016. Архивировано 7 декабря 2015 года.
- ↑ shm_overview(7) - Linux manual page . man7.org. Дата обращения: 4 января 2016. Архивировано 4 января 2016 года.
- ↑ MappedByteBuffer (Java Platform SE 7 ) . docs.oracle.com. Дата обращения: 4 января 2016. Архивировано 15 января 2016 года.
- ↑ Shared Memory Functions in PHP-API . Дата обращения: 26 июня 2014. Архивировано 25 июня 2014 года.
Для улучшения этой статьи желательно:
|