/
memset
/
shared_mem
Обзор
Документация
Войти
/
memset
/
shared_mem
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
sharedmem.cpp
195 строк
9 KB
petrova_ms
Добавлены файлы в репозиторий
06 июн 2026, 13:37
06 июн 2026, 13:37
0993acb
Код
Авторство
О чём код?
/** @file sharedmem.cpp @author Петрова М.С. (memset) @version @date @note Реализация методов класса SharedMem */ #include "sharedmem.h" #include <cstdio> #include <cstring> /// @name Методы класса SharedMem /// @{ /** * @note * - Если нужно создать новую структуру IPC, а не получить ссылку на существующую, * следует в аргументе flag вместе с флагом IPC_CREAT указать флаг IPC_EXCL. * - В результате, если данная структура IPC уже существует, функция вернет признак * ошибки с кодом EEXIST. (Очень напоминает правила определения флагов O_CREAT и O_EXCL в вызове функции open.) * - Если необходимо создать новый сегмент разделяемой памяти (обычно на стороне сервера), * его размер следует определить в аргументе size. * - Если нужно лишь получить ссылку на существующий сегмент (в случае клиента), в аргументе size можно передать 0. * * - Когда создается новый сегмент, его содержимое очищается. * - "0600" - чтение и запись для владельца * * * - После создания сегмента разделяемой памяти процесс может присоединить его к своему адресному пространству с помощью функции shmat. * - Возвращает указатель на сегмент разделяемой памяти в случае успеха, –1 — в случае ошибки. * - Адрес, начиная с которого будет присоединен сегмент разделяемой памяти, зависит от значения аргумента addr и * наличия флага SHM_RND в аргументе flag. * - Если в аргументе addr передано значение 0, сегмент будет присоединен к первому доступному адресу, * который выберет ядро. Это рекомендуемая методика. * - Если в аргументе addr передано ненулевое значение и флаг SHM_RND не указан, сегмент присоединяется, начиная с адреса addr. * - Если в аргументе addr передано ненулевое значение и указан флаг SHM_RND, сегмент будет присоединен с адреса, который вычисляется по формуле: (addr —(addr mod SHMLBA)). * - Имя константы SHM_RND происходит от слова «round» (округлить). * - Имя константы SHMLBA, величина которой всегда представлена степенью числа 2, — от «low boundary address multiple» (множитель адресанижней границы). * Приведенная выше формула округляет адрес вниз до ближайшего кратного числу SHMLBA. */ int SharedMem::init_shared_mem(const key_t memory_key, const uint64_t memory_size) { this->memory_key = memory_key; this->memory_size = memory_size; int err = 0; if((shmid = shmget(memory_key, memory_size, 0666 | IPC_CREAT | IPC_EXCL)) < 0) { err = errno; switch(err) { case EINVAL: { #ifdef DEBUG_PRINTF_SHARED_MEM printf("SharedMem::SharedMem: SH_MEM_ERR проблема с размером \n"); #endif type_status_mem = TYPE_STATUS_SHARED_MEM_ERR_CREATE; } break; case EEXIST: { #ifdef DEBUG_PRINTF_SHARED_MEM printf("SH_MEM_ERR: Уже существует %u \n", memory_key); #endif if((shmid = shmget(memory_key, memory_size, 0666 | IPC_CREAT)) < 0) { #ifdef DEBUG_PRINTF_SHARED_MEM printf("SH_MEM_ERR: Ошибка открытия %u \n", memory_key); #endif } else type_status_mem = TYPE_STATUS_SHARED_MEM_OPEN; } break; case ENOMEM: { #ifdef DEBUG_PRINTF_SHARED_MEM printf("SharedMem::SharedMem: SH_MEM_ERR нет места \n"); #endif type_status_mem = TYPE_STATUS_SHARED_MEM_ERR_CREATE; } break; default: { #ifdef DEBUG_PRINTF_SHARED_MEM printf("SharedMem::SharedMem: SH_MEM_ERR = %s\n", strerror(err)); #endif type_status_mem = TYPE_STATUS_SHARED_MEM_ERR_CREATE; } break; } } else type_status_mem = TYPE_STATUS_SHARED_MEM_CREATE; #ifdef DEBUG_PRINTF_SHARED_MEM printf("SharedMem::SharedMem: TYPE_STATUS_MEM = %i \n", type_status_mem); #endif if(type_status_mem > 0) { int * shmat_result = static_cast<int*>(shmat(shmid, 0, 0)); if(shmat_result == (int *)(-1)) { #ifdef DEBUG_PRINTF_SHARED_MEM printf("\n\n ---------------- Critical error: Can't attach shared memory %u \n\n ", memory_key); #endif type_status_mem = TYPE_STATUS_SHARED_MEM_ERR_OPEN; } else data = reinterpret_cast<uint8_t *>(shmat_result); } return type_status_mem; } /** * @note * По окончании работы с сегментом разделяемой памяти следует вызывать * функцию shmdt для его отсоединения. Обратите внимание: эта функция не удаляет из * системы идентификатор и структуры данных, ассоциированные с сегментом памяти. * Идентификатор продолжает существовать, пока какой-либо процесс (зачастую * сервер) специально не удалит его вызовом функции shmctl с командой IPC_RMID. * * @todo Поток stream_dsp_find - должен вырубаться после stream_sock_find */ SharedMem::~SharedMem() { if(data) shmdt(data); if(type_status_mem == TYPE_STATUS_SHARED_MEM_CREATE) shmctl(shmid, IPC_RMID, 0); } /** * @note * Перед чтением проверка что указатель на адресное пространство не нулевой и * сумма указанного размера и смещения не превышают размер адресного пространства */ int SharedMem::read_from_mem(uint8_t * buff_read, uint64_t size_byte, uint64_t offset_byte) { if((data != nullptr) && ((offset_byte + size_byte) <= memory_size)) { memcpy(buff_read, data + offset_byte, size_byte); return 0; } else return -1; } /** * @note */ void SharedMem::memset_zero() { memset(data, 0, memory_size); } /** * @note * Проверяет, что указатель на адресное пространство не нулевой и * сумма указанного размера и смещения не превышают размер адресного пространства */ int SharedMem::memset_size_zero(uint64_t size_byte, uint64_t offset_byte) { if((data != nullptr) && ((offset_byte + size_byte) <= memory_size)) { memset(data + offset_byte, 0, size_byte); return 0; } else return -1; } /** * @note * Перед записью проверка что указатель на адресное пространство не нулевой и * сумма указанного размера и смещения не превышают размер адресного пространства */ int SharedMem::write_to_mem(const uint8_t * buff_write, uint64_t size_byte, uint64_t offset_byte) { if(((offset_byte + size_byte) <= memory_size) && (data != nullptr)) { //printf("\n\n WRITE_MEM data = %lu offset_byte = %lu size_byte = %lu \n\n", data, offset_byte, size_byte); memcpy(data + offset_byte, buff_write, size_byte); return 0; } else return -1; } ///@}