Совместное использование переменных процессами

Задача
Необходимо найти способ совместного использования информации несколькими процессами, что обеспечивает более быстрый доступ к разделяемому ресурсу.

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

$semaphore_id = 100;
$segment_id = 200;
// захватываем дескриптор семафора, связанного с нужным сегментом памяти
$sem = sem_get($semaphore_id,1,0600);
// обеспечиваем эксклюзивный доступ к семафору
sem_acquire($sem) or die("Can't acquire semaphore");
// определяем дескриптор для разделяемого сегмента памяти
$shm = shm_attach($segment_id,16384,0600);
// возвращаем значение из разделяемого сегмента памяти
$population = shm_get_var($shm,'population');
// обрабатываем значение
$population += ($births + $immigrants - $deaths - $emigrants);
// заносим значение обратно в разделяемый сегмент памяти
shm_put_var($shm,'population',$population);
// освобождаем дескриптор разделяемого сегмента памяти
shm_detach($shm);
// освобождаем дескриптор семафора,
// так чтобы другой процесс мог его получить
sem_release($sem);

Обсуждение
Разделяемый сегмент памяти – это часть оперативной памяти машины, к которой могут получить доступ различные процессы (такие как разнообразные веб-серверы, обрабатывающие запросы).


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

Получить контроль над семафором позволяет функция sem_get(), которая определяет его идентификатор. Первым аргументом функции sem_get() является целочисленный ключ семафора. В качестве ключа может выступать любое целое число, одинаковое для всех программ, которым требуется доступ к определенному семафору. Если семафорс указанным ключом еще не существует, то он создается; второй аргумент (в данном случае 1) устанавливает максимальное количество процессов, которые могут получить доступ к семафору, а права доступа к семафору устанавливаются третьим аргументом (0600) функции sem_get(). Эти права доступа работают так же, как и права доступа к файлу, поэтому 0600 означает, что пользователь, создавший семафор, может читать и записывать их. В этом контексте «пользователь» означает не только процесс, создавший семафор, но и любой процесс с тем же самым идентификатором пользователя.


Права доступа 0600 долж-
ны подойти в большинстве случаев, в которых процессы веб-сервера запускаются от имени одного и того же пользователя.

Функция sem_get() возвращает идентификатор, указывающий на базовый системный семафор. Этот идентификатор позволяет получить контроль над семафором с помощью функции sem_acquire(). Эта функция ожидает возможности захвата семафора (возможно, ожидает, пока другой процесс не освободит семафор) и затем возвращает значение true. В случае ошибки она возвращает false. К ошибкам относятся неверные права доступа или недостаток памяти для создания семафора. Как только семафор захвачен, можно читать из разделяемого сегмента памяти.

Сначала устанавливаем ссылку на выбранный разделяемый сегмент памяти с помощью функции shm_attach(). Как и в функции sem_get(), первым аргументом функции shm_attach() является целочисленный ключ. Однако на этот раз он идентифицирует требуемый сегмент, а не семафор. Если сегмент с указанным ключом не существует, то остальные аргументы его создают. Второй аргумент (16384) представляет размер сегмента в байтах, а последний аргумент задает права доступа к сегменту. Функция shm_attach(200,16384,0600) создает разделяемый сегмент памяти размером 16 Кбайт, читать из которого и записывать в который может только пользователь, его создавший.


Эта функция возвращает идентификатор, необходимый для чтения и записи в разделяемый сегмент памяти.

После подсоединения к сегменту переменные из него извлекают с помощью функции shm_get_var($shm, 'population'). Она заглядывает в разделяемый сегмент памяти, определяемый переменной $shm, и извлекает значение переменной под именем population. В разделяемой памяти можно хранить переменные любого типа. С извлеченной переменной
можно работать так же, как и с другими переменными. Функция shm_put_var($shm,'population',$population) помещает значение переменной $population обратно в разделяемый сегмент памяти в виде переменной под именем population.

Теперь работа с разделяемым сегментом памяти закончена. Отсоединитесь от него с помощью функции shm_detach() и освободите семафор с помощью функции sem_release(), чтобы другой процесс смог его использовать.

Основное преимущество разделяемой памяти заключается в ее скорости. Но так как она располагается в оперативной памяти, то не может хранить слишком большие данные и не сохраняется во время перезагрузки машины (если не принять специальных мер по записи информации, хранящейся в разделяемой памяти, на диск и обратной ее записи после перезапуска компьютера). Кроме того, разделяемая память не поддерживается в Windows.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Обмен значениями без временных переменных
Операторы == и =: как избежать путаницы
Получение дампа содержимого переменных в виде строк
Сериализация данных сложных типов в виде строки
Создание динамического имени переменной

Вернуться в раздел: PHP / 5. Переменные