Skip to content

Instantly share code, notes, and snippets.

@caiorss
Created November 1, 2020 18:58
Show Gist options
  • Save caiorss/d5f8db63803859f6182e271e026498e3 to your computer and use it in GitHub Desktop.
Save caiorss/d5f8db63803859f6182e271e026498e3 to your computer and use it in GitHub Desktop.
Experiment code for POSIX Shared memory IPC on Unix systems
#include <iostream>
#include <string>
#include <cassert>
#include <cstring>
// ----- Unix and Posix headers ---//
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
// Implementation of object allocated in Shared memory
struct Object
{
int x = 0;
double y = 26.2124214;
char dataset[400] = "Hello world";
Object(){
std::cout << " [TRACE] Object created Ok \n" << '\n';
}
void set_x(int x) { this->x = x; }
void set_y(double y) { this->y = y; }
void set_str(const char* value)
{
mempcpy(dataset, value, 200);
}
void show() const
{
std::cout << " [TRACE] Shared memory object =>> "
<< " ; x = " << x
<< " ; y = " << y
<< " ; str = " << dataset
<< '\n';
}
};
constexpr int FAILURE = -1;
constexpr size_t STORAGE_SIZE = sizeof(Object);
constexpr const char* shared_memory_name = "/shared-data";
// Provides shared memory object.
void server_side(const char* shm_name);
// Consumes shared memory object.
void client_side(const char* shm_name);
int main(int argc, char** argv)
{
std::cout << " [INFO] Process Unique Identifier PID = " << ::getpid() << '\n';
std::cout << " [INFO] Storage size in bytes = " << STORAGE_SIZE << '\n';
if(argc < 2){
std::cerr << " [ERROR] Expected command argument. " << '\n';
return EXIT_FAILURE;
}
auto command = std::string{argv[1]};
if(command == "server" ){ server_side(shared_memory_name); }
if(command == "client" ){ client_side(shared_memory_name); }
return 0;
}
// ========= I M P L E M E N T A T I O N S =================//
void server_side(const char* shm_name)
{
// Remove shared memory segment if it already exists.
::shm_unlink(shm_name);
// Attempt to create shared memory segment
// On Linux this segment corresponds to the file: '/dev/shm/<SHM-NAME>'
int fd = shm_open( shm_name
, O_CREAT | O_EXCL | O_RDWR
, S_IRUSR | S_IWUSR
);
// assert => Placeholder for future error handling
assert( fd != FAILURE && "Failed to create shared memory segment" );
// Resize shared memory segment
assert( ::ftruncate(fd, STORAGE_SIZE) != FAILURE );
// Map shared memory segment into process address space
void* pmap = ::mmap( nullptr // Most of the time set to nullptr
, STORAGE_SIZE // Size of memory mapping
, PROT_READ | PROT_WRITE // Allows reading and writing operations
, MAP_SHARED // This flag makes this segment visible by other processes.
, fd // File descriptor
, 0x00 // Offset from beggining of file
);
if(pmap == MAP_FAILED){ perror("mmap"); exit(EXIT_FAILURE); }
// Allocate object in shared memory segment
// using placement 'new operator'
Object* pObj = new (pmap) Object;
assert( pObj != nullptr );
std::cout << " [BEFORE] Before typing RETURN " << '\n';
pObj->show();
std::cout << "\n\n Type return to exit" << '\n';
std::getchar();
std::cout << " [BEFORE] After typing RETURN " << '\n';
pObj->show();
// Mmap cleanup procedure
assert( ::munmap(pmap, STORAGE_SIZE) != FAILURE );
// Remove shared memory segment
::shm_unlink(shm_name);
}
void client_side(const char* shm_name)
{
// Attempt to create shared memory segment
int fd = ::shm_open( shm_name, O_RDWR, 0);
// assert => Placeholder for future error handling
assert( fd != - 1 && "Failed to open shared memory segment" );
// Map shared memory segment into process address space
void* pmap = ::mmap( nullptr // Most of the time to NULL or nullptr
, sizeof STORAGE_SIZE // Size of memory mapping
, PROT_READ | PROT_WRITE // Allows reading and writing operations
, MAP_SHARED // This flag makes this segment visible by other processes.
, fd // File descriptor
, 0x00 // Offset from beggining of file
);
if(pmap == MAP_FAILED){ perror("mmap"); exit(EXIT_FAILURE); }
/* Load object from shared memory knowing only its interface
* (pointer to interface class), without knowing its exact
* implementation or type.
*/
Object* pObj = reinterpret_cast<Object*>(pmap);
std::cout << " Previous object value " << '\n';
pObj->show();
int x;
double y;
std::string str;
std::cout << "Enter x, y and str: ";
std::cin >> x >> y >> str;
pObj->set_x(x);
pObj->set_y(y);
pObj->set_str(str.c_str());
pObj->show();
// assert( ::munmap(pmap, STORAGE_SIZE) != FAILURE );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment