|
//sharedmemory.h |
|
#ifndef SHAREDMEMORY_H |
|
#define SHAREDMEMORY_H |
|
|
|
#include <sys/shm.h> |
|
#include <sys/stat.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <sys/mman.h> |
|
#include <sys/stat.h> /* For mode constants */ |
|
#include <fcntl.h> /* For O_* constants */ |
|
#include <vector> |
|
#include <algorithm> //for std::generate_n |
|
#include <string> |
|
#include <cstdio> |
|
|
|
class SharedMemory |
|
{ |
|
const char *SHM_NAME; |
|
void *memory; |
|
size_t size; |
|
pid_t creator; |
|
std::vector<pid_t> processesWithAccess; |
|
public: |
|
// !!! ctor should be only called in Parent thread !!! |
|
// shared memory is being accessable as long as parent does not destruct the object |
|
SharedMemory(size_t s); |
|
~SharedMemory(); |
|
|
|
// can be called multiple times |
|
void *getPtr(); |
|
|
|
private: |
|
void *getSHM(); |
|
static const char *getRandomMemoryName(size_t len); |
|
}; |
|
|
|
#endif // SHAREDMEMORY_H |
|
|
|
// ============================================================================= |
|
// sharedmemory.cpp |
|
#include "sharedmemory.h" |
|
|
|
SharedMemory::SharedMemory(size_t s) |
|
: SHM_NAME(getRandomMemoryName(100)), creator(getpid()), size(s) { |
|
// via fork() address space is being duplicated - |
|
// so no second construction occurs and only owner (parent) |
|
// has right to unlink shared memory |
|
// children has "creator" member set to pid of parent |
|
|
|
// random memory name allows to create multiple memories in the same parent |
|
// (and even children can create own shared memory, which can be shared with |
|
// children's children) |
|
} |
|
|
|
SharedMemory::~SharedMemory() { |
|
shmdt(memory); |
|
if (getpid() == creator) { |
|
shm_unlink(SHM_NAME); |
|
} |
|
} |
|
|
|
void *SharedMemory::getPtr() { |
|
pid_t thisProc = getpid(); |
|
for (auto&& p : processesWithAccess) { |
|
if (p == thisProc) { |
|
return memory; |
|
} |
|
} |
|
memory = getSHM(); |
|
processesWithAccess.push_back(thisProc); |
|
return memory; |
|
} |
|
|
|
void *SharedMemory::getSHM() { |
|
int shm; |
|
void *memory; |
|
shm = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRWXU | S_IRWXO); |
|
ftruncate(shm, size); |
|
memory = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, shm, 0); |
|
return memory; |
|
} |
|
|
|
const char *SharedMemory::getRandomMemoryName(size_t len) |
|
{ |
|
srand(time(NULL)); |
|
auto randchar = []() -> char |
|
{ |
|
const char charset[] = |
|
"0123456789" |
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
|
"abcdefghijklmnopqrstuvwxyz"; |
|
const size_t max_index = (sizeof(charset) - 1); |
|
return charset[ rand() % max_index ]; |
|
}; |
|
std::string str(len,0); |
|
std::generate_n( str.begin(), len, randchar ); |
|
str = "/" + str; |
|
return str.data(); |
|
} |