How to do it...

In this recipe, we will learn how to use a Linux shared memory API for data exchange between two or more applications:

  1. In your working ~/test directory, create a subdirectory called shmem.
  2. Use your favorite text editor to create a shmem.cpp file in the shmem subdirectory. Define the SharedMem class, starting with common headers and constants:
#include <algorithm>
#include <iostream>
#include <chrono>
#include <thread>

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

const char* kSharedMemPath = "/sample_point";
const size_t kPayloadSize = 16;

using namespace std::literals;

template<class T>
class SharedMem {
int fd;
T* ptr;
const char* name;

public:
  1. Then, define a constructor that does most of the work:
SharedMem(const char* name, bool owner=false) {
fd = shm_open(name, O_RDWR | O_CREAT, 0600);
if (fd == -1) {
throw std::runtime_error("Failed to open a shared memory region");
}
if (ftruncate(fd, sizeof(T)) < 0) {
close(fd);
throw std::runtime_error("Failed to set size of a shared memory
region");
};
ptr = (T*)mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (!ptr) {
close(fd);
throw std::runtime_error("Failed to mmap a shared memory region");
}
this->name = owner ? name : nullptr;
std::cout << "Opened shared mem instance " << name << std::endl;
}
  1. Add the definition of the destructor:
    ~SharedMem() {
munmap(ptr, sizeof(T));
close(fd);
if (name) {
std::cout << "Remove shared mem instance " << name << std::endl;
shm_unlink(name);
}
}
  1. Finalize the class definition with a small method that returns a reference to the shared object:
    T& get() const {
return *ptr;
}
};
  1. Our SharedMem class can work with different data types. Let's declare a custom data structure that we want to use:
struct Payload {
uint32_t index;
uint8_t raw[kPayloadSize];
};
  1. Now add code that writes data to the shared memory:
void producer() {
SharedMem<Payload> writer(kSharedMemPath);
Payload& pw = writer.get();
for (int i = 0; i < 5; i++) {
pw.index = i;
std::fill_n(pw.raw, sizeof(pw.raw) - 1, 'a' + i);
pw.raw[sizeof(pw.raw) - 1] = '';
std::this_thread::sleep_for(150ms);
}
}
  1. Also, add code that reads data from the shared memory:
void consumer() {
SharedMem<Payload> point_reader(kSharedMemPath, true);
Payload& pr = point_reader.get();
for (int i = 0; i < 10; i++) {
std::cout << "Read data frame " << pr.index << ": " << pr.raw << std::endl;
std::this_thread::sleep_for(100ms);
}
}
  1. Add the main function to tie everything together, as shown in the following code:
int main() {

if (fork()) {
consumer();
} else {
producer();
}
}
  1. Create a file called CMakeLists.txt in the loop subdirectory with the following content:
cmake_minimum_required(VERSION 3.5.1)
project(shmem)
add_executable(shmem shmem.cpp)
target_link_libraries(shmem rt)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

SET(CMAKE_CXX_FLAGS "--std=c++14")
set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabi-g++)
  1. Build the application and copy the resulting executable binary to the target system. Use recipes from Chapter 2,Setting Up the Environment, to do it.
  2. Switch to the target system terminal. Log in using user credentials, if needed.
  3. Run the binary.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.93.210