Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 131 · От строк к межпроцессному обмену

Shmop: общий блок байтов и полный справочник

Все шесть функций и класс Shmop: режимы, смещения, неполная запись, формат пакета и жизненный цикл.

Общий блок байтов: что это и зачем

Локальный сборщик телеметрии подготовил пакет байтов, а PHP обработчик должен его прочитать. Если оба процесса работают в одной ОС и договорились о формате, они могут использовать общий сегмент памяти. shmop предоставляет именно чтение и запись байтов по позиции. В отличие от sysvshm, здесь нет ключей PHP переменных и автоматической сериализации массива.

Пакет A42|0007
  1. Общий блок: позиции 0…7
  2. Позиции 0…3: A42| — код товара
  3. Позиции 4…7: 0007 — текстовое число
  4. read(0,4) получил A42|
  5. read(4,4) получил 0007

Модель — линейка с ячейками размером в один байт. Вы сами договариваетесь, где начинается поле и как распознаётся конец. Это не массив с ключами, не поток с автоматически растущим курсором и не база данных. Условный пример использует ASCII, чтобы одна буква занимала один байт; русский текст UTF-8 требует считать байты отдельно от символов.

Записать и прочитать два поля по смещениюСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$packet = 'A42|0007';
$written = shmop_write($block, $packet, 0);
if ($written !== strlen($packet)) throw new RuntimeException('Пакет записан не целиком');
echo shmop_read($block, 0, 4), "\n";
echo shmop_read($block, 4, 4), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42|
0007

$block — ручка блока, строка $packet — содержимое, 0 — первая позиция. strlen считает байты. Третий аргумент read — сколько байтов взять, третий аргумент write — откуда писать. finally помечает собственный сегмент к удалению и освобождает объект.

Установка, платформы, объекты и файлы примеров

При сборке PHP расширение включается --enable-shmop; у пакетной установки проверьте совместимый модуль своего дистрибутива. На Windows существует php_shmop.dll и реализация через Windows mappings. В PHP 8.0 функция open возвращает объект Shmop вместо resource. Наличие shmop не означает наличия sysvsem: это независимые расширения.

Часть настройкиСмысл
Проверкаextension_loaded("shmop") / function_exists("shmop_open") именно в используемом SAPI. CLI и PHP-FPM могут иметь разные ini.
INI / константыУ shmop нет собственного набора runtime ini директив и предопределённых констант. Размер задаётся при создании, системные лимиты относятся к ОС.
Windows / UnixПрава Unix 0600 и жизненный цикл IPC_RMID нельзя без проверки перенести на mappings Windows. Тестируемые примеры здесь создают только приватные блоки key=0 внутри одного процесса.
Общее окружениеОдинаковый key в разных IPC namespaces/контейнерах не означает один блок. Две физические машины не разделяют System V shared memory.
ОбъектShmop — непрозрачная ручка без публичных методов/свойств. Освобождается автоматически после исчезновения всех PHP ссылок.
Файл shmop-lab.php: новый приватный учебный блокПример для указанного окружения
<?php
function lessonBytes(int $capacity = 256): Shmop {
    $block = shmop_open(0, 'n', 0600, $capacity);
    if ($block === false) throw new RuntimeException('Не создан учебный блок');
    return $block;
}
Ожидаемый результат
Объявлена функция lessonBytes; блок создастся только при её вызове.

key=0 означает IPC_PRIVATE. Каждый вызов создаёт отдельный блок и не подключается к чужому. Вне этого файла примеры оборачивают работу в try/finally. При Windows процессы проверки дополнительно завершаются и освобождают собственные mapping handles. Это контекстный пример для указанной среды; здесь проверен синтаксис, многопроцессное выполнение не заявляется.

Четыре режима и владение жизненным циклом

Для независимых участников нужен согласованный ненулевой key, например через ftok. Key не уникален автоматически и не является секретом авторизации. Владелец создаёт новый блок режимом n и не удаляет чужой, если n вернул отказ. Читатель открывает существующий a, писатель w. Режим c удобен для open-or-create, но не сообщает, кто создал блок: первый писатель не должен без протокола обнулять уже существующие данные.

РежимПоведение
aОткрыть существующий только для чтения; permissions=0, size=0.
wОткрыть существующий для чтения/записи; permissions=0, size=0.
cСоздать либо открыть существующий read/write. Положительный size нужен для режима создания; существующий блок не расширяется.
nСоздать новый эксклюзивно; существующий ненулевой key даёт отказ. key=0 — специальное создание приватного блока.

На Unix попытка открыть существующий меньший сегмент через c с большим size может дать EINVAL. Это не команда увеличить память. Для изменения ёмкости нужен отдельный новый сегмент, перенос под согласованной блокировкой, переключение участников и последующее удаление старого. Не делайте delete/open поверх активных readers.

Длина, кодировка и граница сообщения

Объём блока и длина полезного сообщения — разные числа. Если сначала записать восемь байтов, а потом два в offset=0, оставшиеся шесть не исчезнут. Для двоичного протокола храните точную длину. trim/rtrim не является универсальным решением: нулевой байт может быть частью легальных данных.

Сохранить JSON с четырёхбайтовой длинойСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$json = json_encode(['sku' => 'A42', 'qty' => 7], JSON_THROW_ON_ERROR);
$length = strlen($json);
$header = pack('N', $length);
$packet = $header . $json;
if (strlen($packet) > shmop_size($block)) throw new LengthException('Пакет не помещается');
if (shmop_write($block, $packet, 0) !== strlen($packet)) throw new RuntimeException('Короткая запись');
$decodedHeader = unpack('Nlength', shmop_read($block, 0, 4));
$payloadLength = $decodedHeader['length'];
if ($payloadLength < 1 || $payloadLength > shmop_size($block) - 4) throw new RuntimeException('Неверная длина');
$payload = shmop_read($block, 4, $payloadLength);
$stock = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
if (!is_array($stock) || !is_string($stock['sku'] ?? null) || !is_int($stock['qty'] ?? null)) {
    throw new RuntimeException('Неверная структура');
}
echo $stock['sku'], ': ', $stock['qty'], "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42: 7

pack("N") — четырёхбайтовое беззнаковое целое в сетевом порядке байтов; unpack восстанавливает его. Все стороны должны согласовать этот формат. Этот пример однопроцессный: одна memcpy запись не обещает атомарности целого пакета при конкуренции.

Для реального обмена добавьте версию формата, допустимый предел длины, явную инициализацию и один общий механизм блокировки для writers и readers. Сначала захват, затем чтение длины и тела в одном участке, затем освобождение. Отдельная запись «готово» не делает произвольный протокол атомарным. Нельзя объявлять отсутствие гонок только потому, что длина записана последней. Синхронизация и memory ordering требуют гарантированного общего примитива.

Освобождение ссылки, delete и устаревший close

Отличие управления объектом от удаления блока
  1. Владелец создал блок
  2. У нескольких процессов есть подключения
  3. delete на Unix пометил блок
  4. Объекты освободились → detach
  5. Последнее подключение ушло → Unix освободил блок

С PHP 8 shmop_close устарела и ничего не делает. Для прекращения собственного доступа освободите все ссылки на объект: unset одной переменной недостаточно, если тот же объект хранится в другой. Для удаления системного блока нужен shmop_delete владельцем до освобождения его последней ручки. Unix может держать помеченный сегмент, пока другие участники подключены. Windows mappings имеют собственные правила lifetime; успешный delete не является переносимым обещанием немедленного пересоздания того же key.

Общий блок не долговечен как база данных. Планируйте восстановление после перезапуска, срок жизни данных и остановку участников. Не вызывайте delete при каждом чтении — это решение владельца после координации. Для завершения примеров key0 гарантирует изоляцию; для проекта храните договор key/владельца/версии, а не список всех ресурсов ОС для массового удаления.

Стоимость, альтернативы и задания

ПотребностьЧто выбрать/измерять
PHP массивы между процессамиsysvshm сам сериализует переменные, но тоже требует lock; shmop нужен, когда вы управляете форматом байтов.
Команда обработчикуОчередь сообщений либо socket часто выражает запрос/ответ яснее, чем ручная общая структура.
Состояние магазина после перезапускаБаза данных/надёжное хранилище; блок памяти не заменяет транзакции и долговечность.
Большой пакетread создаёт PHP строку длиной N, write копирует данные. Учитывайте копирование/декодирование и пиковую память.
Частые мелкие операцииСчитайте overhead блокировок, число копий, размер пакета и время ожидания; нет универсальной гарантии превосходства над кешем/БД.

Практика: замените второй write в карточке write на запись по offset=strlen первой строки — получится склейка без перекрытия. Затем сократите JSON payload: при framing читатель возьмёт только новую длину, старый хвост не попадёт в JSON. Для текста «Привет» сравните strlen с числом символов; не разрезайте UTF-8 на произвольном байте. Следующие темы: IPC и семафоры, локальные sockets, байтовые строки.

Функции и методы этой темы

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

shmop_openСоздать блок или подключиться с нужными правами доступа.

PHP 4.0.4+ · shmop

shmop_open(int $key, string $mode, int $permissions, int $size): Shmop|false

Создать блок или подключиться с нужными правами доступа.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
keyIPC ключ; 0 новый приватный блок. Для общего ненулевого key проверяйте ftok/namespace/владение.
modeОдна буква a read-only existing, w read/write existing, c open-or-create, n exclusive create.
permissionsВосьмеричные биты при создании, 0 для a/w.
sizeПоложительные байты для c/n; 0 при a/w. Не увеличивает existing block.
Отказfalse и E_WARNING от ОС; неверный mode/size создания — ValueError. PHP8 вернул объект вместо resource.
shmop_open: движение байтов
  1. key0 + n + 0600 + 128
  2. ОС создала отдельный блок
  3. open → Shmop
  4. size проверяет реальную ёмкость

Нужно место для небольшого бинарного пакета. Все четыре аргумента обязательны: key выбирает системный сегмент, mode определяет создание/доступ, permissions — Unix права, size — запрошенную ёмкость в байтах. Режим n с приватным key0 подходит для самостоятельного эксперимента.

Создать свой блок и проверить доступную ёмкостьСамостоятельный пример
<?php
declare(strict_types=1);

$block = shmop_open(0, 'n', 0600, 128);
if ($block === false) throw new RuntimeException('Не создан блок');
try { echo shmop_size($block) >= 128 ? "Места достаточно\n" : "Проверьте размер\n"; }
finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Места достаточно

0600 — восьмеричные права. Фактический размер узнают функцией size; пример не угадывает платформенные накладные расходы и не использует чужой key.

Отловить ошибку режима до обращения к ОССамостоятельный пример
<?php
declare(strict_types=1);

try { shmop_open(0, 'rw', 0600, 128); }
catch (ValueError $error) { echo "Нужна одна буква режима: a, w, c или n\n"; }
Ожидаемый результат
Нужна одна буква режима: a, w, c или n

rw похоже на файловый режим, но shmop принимает ровно одну допустимую букву. Нулевая ёмкость запрещена для c/n; у a/w при открытии существующего используют size=0.

Подключить read-only читателя к своему Unix сервисуПример для указанного окружения
<?php
declare(strict_types=1);

$key = ftok(__DIR__ . '/app.ipc', 'B');
if ($key === -1 || $key === 0) throw new RuntimeException('Нет общего ключа');
$block = shmop_open($key, 'a', 0, 0);
if ($block === false) throw new RuntimeException('Владелец ещё не создал блок либо нет доступа');
try { echo shmop_read($block, 0, 4), "\n"; }
finally { unset($block); }
Ожидаемый результат
A42| — если владелец учебного Unix сервиса создал согласованный блок с таким заголовком.

Только ваш выделенный IPC namespace и файл app.ipc, общий с владельцем. Читатель не удаляет сегмент. Если для actual payload нужны согласованные чтения, вокруг чтения применяется общий lock. Это контекстный пример для указанной среды; здесь проверен синтаксис, многопроцессное выполнение не заявляется.

Рядом: shmop_size, shmop_write, shmop_delete.

shmop_sizeУзнать ёмкость блока в байтах.

PHP 4.0.4+ · shmop

shmop_size(Shmop $shmop): int

Узнать ёмкость блока в байтах.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
shmopВалидный объект open.
РезультатРазмер сегмента, не длина payload и не свободное место.
ВерсияВ PHP8 аргумент Shmop, прежде resource.
shmop_size: движение байтов
  1. open запросил блок
  2. size вернул доступный объём
  3. strlen посчитал пакет
  4. сравнили до записи

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

Проверить пакет перед записьюСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$payload = 'A42|0007';
$capacity = shmop_size($block);
echo strlen($payload) <= $capacity ? "Пакет помещается\n" : "Пакет слишком большой\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Пакет помещается

Сравниваются байты. Проверка не резервирует блок для текущего процесса; конкурентные writers всё равно должны иметь общий lock.

Ёмкость не уменьшается после короткой записиСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$before = shmop_size($block);
shmop_write($block, 'OK', 0);
$after = shmop_size($block);
echo $before === $after ? "Ёмкость прежняя\n" : "Ёмкость изменилась\n";
echo 'Полезных байтов сейчас: ', strlen('OK'), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Ёмкость прежняя
Полезных байтов сейчас: 2

Чтение всей ёмкости вернуло бы также незанятый/старый хвост. Это не способ узнать длину нового сообщения.

Рядом: shmop_open, shmop_read, shmop_write.

shmop_readСкопировать выбранные байты в PHP строку.

PHP 4.0.4+ · shmop

shmop_read(Shmop $shmop, int $offset, int $size): string

Скопировать выбранные байты в PHP строку.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
offsetБайтовое смещение от 0 до ёмкости включительно.
sizeБайты; 0 означает остаток блока. Положительный размер не должен пересекать конец.
РезультатBinary-safe string, включая нули. В PHP8 диапазоны нарушены → ValueError.
shmop_read: движение байтов
  1. Пакет A42|0007
  2. offset=4, size=4
  3. прочитаны байты 0007
  4. преобразованы после проверки формата

Чтобы прочитать код товара, указывают начало поля и его длину. Результат — PHP строка, которая умеет хранить нулевые байты. Чтение не удаляет данные и не изменяет позицию следующего чтения: каждый offset задаётся заново.

Прочитать нужное поле, а не весь сегментСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'A42|0007', 0);
$quantityText = shmop_read($block, 4, 4);
echo 'Количество: ', (int)$quantityText, "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Количество: 7

В согласованном учебном ASCII формате поле 4…7 содержит четыре десятичные цифры. Для внешних данных проверяйте формат до (int), иначе мусор может превратиться в неожиданное число.

Понять особое значение size=0Самостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$capacity = shmop_size($block);
shmop_write($block, 'END', $capacity - 3);
echo shmop_read($block, $capacity - 3, 0), "\n";
echo strlen(shmop_read($block, $capacity, 0)), "\n";
try { shmop_read($block, $capacity, 1); }
catch (ValueError $error) { echo "За границей блока\n"; }
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
END
0
За границей блока

size=0 означает «до конца», а не всегда пустую строку. Только offset в самом конце даёт пустой результат; запрос хотя бы одного байта за концом запрещён.

offset и size неотрицательны, offset ≤ capacity, offset+size ≤ capacity. В PHP8 нарушение вызывает ValueError, а не старое false. Не передавайте непроверенную длину из заголовка: прежде убедитесь, что она помещается. Чтение нескольких полей по отдельности может смешать версии при параллельной записи; даже одна read не объявлена атомарным снимком произвольного пакета.

Рядом: shmop_size, shmop_write.

shmop_writeЗаменить байты и узнать фактически записанное количество.

PHP 4.0.4+ · shmop

shmop_write(Shmop $shmop, string $data, int $offset): int

Заменить байты и узнать фактически записанное количество.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
dataBinary-safe строка; PHP массив сперва нужно закодировать по договору.
offsetОт 0 до capacity. offset=capacity законен и даёт 0 записанных байтов.
Результатmin(strlen(data), capacity-offset). Проверяйте полную длину.
Ошибки PHP8.5Неверный offset — ValueError; read-only attachment — Error; неправильный тип — TypeError.
shmop_write: движение байтов
  1. В блоке ABCDEFGH
  2. write OK с offset0
  3. заменены только A и B
  4. итог OKCDEFGH

Запись заменяет байты по указанному offset. Она не добавляет данные в конец автоматически, не обнуляет оставшийся хвост и не расширяет блок. Возвращается число действительно записанных байтов; при нехватке места хвост строки не записывается, поэтому сравнение с strlen обязательно.

Увидеть старый хвост после короткой заменыСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'ABCDEFGH', 0);
shmop_write($block, 'OK', 0);
echo shmop_read($block, 0, 8), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
OKCDEFGH

Если новое сообщение должно быть только OK, читатель обязан знать длину 2. Для фиксированного текстового поля можно явно дополнить поле согласованным padding, но это правило формата, не автоматизм write.

Распознать частичную запись у края блокаСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$capacity = shmop_size($block);
$payload = 'ABCDEF';
$written = shmop_write($block, $payload, $capacity - 3);
echo 'Записано: ', $written, ' из ', strlen($payload), "\n";
echo shmop_read($block, $capacity - 3, 3), "\n";
echo shmop_write($block, 'X', $capacity), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Записано: 3 из 6
ABC
0

Запись внутри допустимого offset может быть короткой без исключения. В самом конце остаётся ноль места: вернётся 0. Перед изменением целого пакета лучше заранее проверить capacity и защищать операцию общим lock.

Разместить две строки последовательноСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
$first = 'A42|';
$second = '0007';
$packetLength = strlen($first) + strlen($second);
if ($packetLength > shmop_size($block)) throw new LengthException('Не помещается');
if (shmop_write($block, $first, 0) !== strlen($first)) throw new RuntimeException('Первая запись короткая');
if (shmop_write($block, $second, strlen($first)) !== strlen($second)) throw new RuntimeException('Вторая запись короткая');
echo shmop_read($block, 0, $packetLength), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
A42|0007

Смещение второй строки — число байтов первой. Два write не становятся одной атомарной операцией: другие процессы должны читать их под общей блокировкой либо по иному корректному протоколу публикации.

PHP 8.5.11 при записи в read-only объект выбрасывает Error, хотя краткая таблица manual объединяет этот случай с ValueError диапазона. offset вне 0…capacity вызывает ValueError. У Shmop нет встроенного compare-and-swap; read → увеличить число → write без синхронизации теряет обновления. Для UTF-8 strlen и offsets относятся к байтам: частичная запись может оборвать символ.

Рядом: shmop_read, shmop_size.

shmop_deleteПометить системный сегмент к удалению владельцем.

PHP 4.0.4+ · shmop

shmop_delete(Shmop $shmop): bool

Пометить системный сегмент к удалению владельцем.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
shmopРучка принадлежащего приложению сегмента.
Результатtrue запрос принят, false и warning при системном отказе, например нет полномочий владельца.
LifetimeUnix удаление завершается после последнего detach. Windows mappings имеют иной жизненный цикл.
shmop_delete: движение байтов
  1. Владелец остановил группу
  2. delete запросил удаление
  3. последние объекты освободились
  4. Unix удалил сегмент

Когда закончилась вся группа участников, владелец освобождает системный ресурс. На Unix функция помечает сегмент к удалению; физически он сохраняется, пока остаются подключения. Поэтому слово delete не означает, что переменная Shmop тут же стала null или память немедленно исчезла у всех читателей.

Пометить свой блок и освободить ручкуСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
try {
    if (!shmop_delete($block)) throw new RuntimeException('Не отмечен к удалению');
    echo "Владелец запросил удаление\n";
} finally { unset($block); }
Ожидаемый результат
Владелец запросил удаление

Только приватный блок текущего эксперимента. unset освобождает единственную ссылку PHP; на Windows окончательный lifetime дополнительно связан с mapping handles процесса.

Завершить ресурс даже при ошибке обработкиСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
try {
    try { throw new RuntimeException('Неверный пакет'); }
    finally { shmop_delete($block); unset($block); echo "Учебный ресурс завершён\n"; }
} catch (RuntimeException $error) { echo "Ошибка обработки учтена\n"; }
Ожидаемый результат
Учебный ресурс завершён
Ошибка обработки учтена

В production один reader не удаляет общий блок в своём finally; это делает владелец после остановки всей группы. Здесь ресурс был создан только ради примера.

Рядом: shmop_open, shmop_close.

shmop_closeУстаревший вызов закрытия: в PHP8 не оказывает действия.

PHP 4.0.4+ · shmop

shmop_close(Shmop $shmop): void  // deprecated since PHP 8.0

Устаревший вызов закрытия: в PHP8 не оказывает действия.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
АргументВ PHP8 Shmop, в старых версиях resource.
Результатvoid; в PHP8 NOP с уведомлением об устаревании.
ЗаменаОсвободить все ссылки на объект. Для владельца системного ресурса отдельно shmop_delete.
shmop_close: движение байтов
  1. Старый код вызвал close
  2. PHP8 сообщает deprecated
  3. объект всё ещё доступен
  4. lifetime завершает освобождение последней ссылки

Эта функция нужна читателю для понимания старого кода, а не для нового шаблона cleanup. Начиная с PHP8.0 она deprecated и ничего не делает: объект освобождается автоматически, когда на него больше нет ссылок. Старое resource-закрытие из PHP7 переносится не механически.

Убедиться, что close больше не закрывает доступСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
shmop_write($block, 'OK', 0);
set_error_handler(static fn() => true, E_DEPRECATED);
try { shmop_close($block); }
finally { restore_error_handler(); }
echo shmop_read($block, 0, 2), "\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
OK

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

Понять время освобождения при двух PHP ссылкахСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes();
$reader = $block;
unset($block);
try {
    shmop_write($reader, 'OK', 0);
    echo shmop_read($reader, 0, 2), "\n";
} finally { shmop_delete($reader); unset($reader); }
Ожидаемый результат
OK

Присваивание объекта создало ещё одну ссылку на ту же ручку, не копию сегмента. unset первой переменной не закрывает объект, пока он доступен через $reader.

Рядом: shmop_delete, shmop_open.

ShmopНепрозрачная ручка блока байтов PHP8.

PHP 8.0+ · shmop

final class Shmop

Непрозрачная ручка блока байтов PHP8.

Объект Shmop обозначает блок общих байтов ОС. Параметр offset — позиция байта с нуля; size — число байтов, а не букв. Например, shmop_read($block, 0, 4) читает первые четыре байта. Функции не добавляют заголовок, JSON разбор, блокировку и перемещение курсора вместо приложения.

Сначала: байты, ёмкость и учебный блок. Связанные основы: строки, параметры функций, семафоры и PHP общая память.

ДоговорЗначение
Созданиеshmop_open → Shmop|false. new запрещён.
РаботаПередать объект в shmop_read/write/size/delete.
ОграниченияНет публичных пользовательских членов; не сериализуется/не клонируется.
ОсвобождениеАвтоматическое после последней ссылки; не заменяет delete системного сегмента.
Shmop: движение байтов
  1. open вернул Shmop
  2. read скопировал байты в строку
  3. объект передали другой переменной
  4. последний unset освобождает attachment

Shmop — final класс расширения, введённый в PHP8 вместо resource. У него нет пользовательских методов, свойств и открытого конструктора. Он обозначает attachment к системному блоку. Данные по-прежнему читаются функциями shmop_read/write, а не $block->data.

Проверить тип современного подключенияСамостоятельный пример
<?php
declare(strict_types=1);

require __DIR__ . '/shmop-lab.php';
$block = lessonBytes(256);
try {
echo $block instanceof Shmop ? "Объект Shmop\n" : "Другой тип\n";
echo is_resource($block) ? "resource\n" : "Это уже не resource\n";
} finally { shmop_delete($block); unset($block); }
Ожидаемый результат
Объект Shmop
Это уже не resource

Обновление PHP7→8 требует изменить resource checks. Проверка типа не подтверждает формат данных и наличие требуемой блокировки.

Создавать ручку только через функцию расширенияСамостоятельный пример
<?php
declare(strict_types=1);

try { new Shmop(); }
catch (Error $error) { echo "Используйте shmop_open\n"; }
Ожидаемый результат
Используйте shmop_open

Непосредственное создание запрещено: объект должен получить действующий attachment. Сериализация, клонирование и добавление динамических свойств тоже не поддержаны.

Рядом: shmop_open, shmop_close, shmop_delete.

Источники и обсуждения

Код и руководство с собой

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

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.