и дополнительным отключением прерываний на момент копирования,
А зачем? Вы же из прерывания не работаете с разделяемой памятью? А так - у вас блокировка на семафоре. В принципе, насколько мне известно, так с этой памятью и работают.
Я, например, делал с такими обёртками:
cmmap.h
#ifndef C_MMAP_H
#define C_MMAP_H
//****************************************************************************************************
//класс работы с mmap
//****************************************************************************************************
//****************************************************************************************************
//подключаемые библиотеки
//****************************************************************************************************
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
//****************************************************************************************************
//класс работы с mmap
//****************************************************************************************************
class CMMAP
{
private:
uint8_t *SharedMemoryPtr;//указатель на блок памяти
size_t Len;
public:
//конструктор
CMMAP(void *add,size_t len,int prot,int flags,int fildes,off_t offr)
{
Len=len;
void *ptr=mmap(add,len,prot,flags,fildes,offr);
SharedMemoryPtr=NULL;
if (ptr!=MAP_FAILED) SharedMemoryPtr=reinterpret_cast<uint8_t*>(ptr);
}
//деструктор
~CMMAP()
{
if (SharedMemoryPtr!=NULL) munmap(SharedMemoryPtr,Len);
}
//получить адрес памяти
uint8_t* GetPtr(void)
{
return(SharedMemoryPtr);
}
//узнать, выполнено ли подключение к памяти
bool IsCreated(void)
{
if (SharedMemoryPtr!=NULL) return(true);
return(false);
}
};
#endif
craiicsemaphore.h
#ifndef C_RAII_CSEMAPHORE_H
#define C_RAII_CSEMAPHORE_H
//====================================================================================================
//описание
//====================================================================================================
//Класс RAII для работы с семафором
//====================================================================================================
//подключаемые библиотеки
//====================================================================================================
#include "csemaphore.h"
//====================================================================================================
//класс RAII для семафора
//====================================================================================================
class CRAIICSemaphore
{
private:
CSemaphore *cSemaphore_Ptr;//указатель на семафор
bool Locked;//состояние семафора
public:
CRAIICSemaphore(CSemaphore *cSemaphore_Set_Ptr)//конструктор
{
Locked=false;
if (cSemaphore_Set_Ptr==NULL) return;
cSemaphore_Ptr=cSemaphore_Set_Ptr;
Lock();
}
~CRAIICSemaphore()
{
if (cSemaphore_Ptr==NULL) return;
Unlock();
}
//заблокировать
void Lock(void)
{
if (cSemaphore_Ptr==NULL) return;
if (Locked==true) return;
cSemaphore_Ptr->Lock();
Locked=true;
}
//разблокировать
void Unlock(void)
{
if (cSemaphore_Ptr==NULL) return;
if (Locked==false) return;
cSemaphore_Ptr->Unlock();
Locked=false;
}
};
#endif
csemaphore.h
#ifndef C_SEMAPHORE_H
#define C_SEMAPHORE_H
//****************************************************************************************************
//класс работы с семафором
//****************************************************************************************************
//****************************************************************************************************
//подключаемые библиотеки
//****************************************************************************************************
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
//****************************************************************************************************
//класс работы с семафором
//****************************************************************************************************
class CSemaphore
{
private:
sem_t *Semaphore;
public:
//конструктор
CSemaphore(const char *name,int oflag,mode_t mode,unsigned int value)
{
Semaphore=sem_open(name,oflag,mode,value);
}
//деструктор
~CSemaphore()
{
if (Semaphore!=SEM_FAILED) sem_close(Semaphore);
//sem_unlink(SHARED_MEMORY_OBJECT_NAME);//уничтожение объекта семафора (можно не делать, чтобы его не потерять в других процессах)
}
//получить семафор
sem_t* GetHandle(void)
{
return(Semaphore);
}
//узнать, создан ли семафор
bool IsCreated(void)
{
if (Semaphore!=SEM_FAILED) return(true);
return(false);
}
//заблокировать семафор
void Lock(void)
{
if (IsCreated()==false) return;
sem_wait(Semaphore);
}
//разблокировать семафор
void Unlock(void)
{
if (IsCreated()==false) return;
sem_post(Semaphore);
}
};
#endif
cshm.h
#ifndef C_SHM_H
#define C_SHM_H
//****************************************************************************************************
//класс работы с дескриптором разделяемой памяти
//****************************************************************************************************
//****************************************************************************************************
//подключаемые библиотеки
//****************************************************************************************************
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
#include <fcntl.h>
#include <stdio.h>
//****************************************************************************************************
//класс работы с дескриптором разделяемой памяти
//****************************************************************************************************
class CShM
{
private:
int SharedMemory;//дескриптор разделяемой памяти
public:
//конструктор
CShM(const char *name,int oflag,mode_t mode)
{
SharedMemory=shm_open(name,oflag,mode);
}
//деструктор
~CShM()
{
if (SharedMemory>=0) close(SharedMemory);
//shm_unlink(SHARED_MEMORY_OBJECT_NAME);//уничтожение объекта разделяемой памяти (можно не делать, чтобы её не потерять в других процессах)
}
//получить дескриптор разделяемой памяти
int GetHandle(void)
{
return(SharedMemory);
}
//узнать, выполнено ли подключение к памяти
bool IsCreated(void)
{
if (SharedMemory>=0) return(true);
return(false);
}
};
#endif
А дальше я делаю так (класс CUniquePtr - самодельный "умный" указатель - в 6.3 у меня штатного в stl нет):
static const std::string SHARED_MEMORY_OBJECT_NAME="/ipk_model_shared_memory";//имя разделяемой памяти
static const std::string SEMAPHORE_OBJECT_NAME="/ipk_model_semaphore";//имя семафора
static const uint32_t SHARED_MEMORY_OBJECT_SIZE=1024;//размер разделяемой области памяти
CUniquePtr<CShM> cUniquePtr_CShM;//указатель на дескриптор разделяемой памяти
CUniquePtr<CMMAP> cUniquePtr_CMMAP;//указатель на разделяемую память
CUniquePtr<CSemaphore> cUniquePtr_CSemaphore;//указатель на семафор
//создаём разделяемую память
cUniquePtr_CShM.Set(new CShM(SHARED_MEMORY_OBJECT_NAME.c_str(),O_CREAT|O_RDWR,S_IRWXO|S_IRWXG|S_IRWXU));
if (cUniquePtr_CShM.Get()->IsCreated()==true)
{
if (ftruncate(cUniquePtr_CShM.Get()->GetHandle(),SHARED_MEMORY_OBJECT_SIZE+1)>=0)
{
cUniquePtr_CMMAP.Set(new CMMAP(0,SHARED_MEMORY_OBJECT_SIZE+1,PROT_WRITE|PROT_READ,MAP_SHARED,cUniquePtr_CShM.Get()->GetHandle(),0));
}
}
//создаём семафор
cUniquePtr_CSemaphore.Set(new CSemaphore(SEMAPHORE_OBJECT_NAME.c_str(),O_CREAT|O_RDWR,S_IRWXO|S_IRWXG|S_IRWXU,1));
...
//И работаем с ней:
//----------------------------------------------------------------------------------------------------
//задать состояние в памяти
//----------------------------------------------------------------------------------------------------
void CErrorsBased::WriteState(void)
{
if (cUniquePtr_CMMAP.Get()==NULL) return;
if (cUniquePtr_CMMAP.Get()->IsCreated()==false) return;
uint8_t *ptr=cUniquePtr_CMMAP.Get()->GetPtr();
...
}
//----------------------------------------------------------------------------------------------------
//считать состояние в памяти
//----------------------------------------------------------------------------------------------------
void CErrorsBased::ReadState(void)
{
if (cUniquePtr_CMMAP.Get()==NULL) return;
if (cUniquePtr_CMMAP.Get()->IsCreated()==false) return;
uint8_t *ptr=cUniquePtr_CMMAP.Get()->GetPtr();
...
}
//----------------------------------------------------------------------------------------------------
//задать состояние и записать в память
//----------------------------------------------------------------------------------------------------
void CErrorsBased::SetState(void)
{
if (cUniquePtr_CSemaphore.Get()->IsCreated()==false) return;
//блокируем семафор
{
CRAIICSemaphore cRAIICSemaphore(cUniquePtr_CSemaphore.Get());
{
ReadState();
WriteState();
}
}
}