0

I am cross-compiling on a Ubuntu 24.04 host for a Raspberry Pi Zero2 W. I want to be able to access data for a device on the i2c bus not only from multiple instances in the same program but also from different processes. So, I believe I need to use shared memory and I need a lock in that shared memory so only 1 instance of 1 process can communicate with the device at a time.

So, I have the following:

int shmem_fd = shm_open(shmem_fname.c_str(), O_RDWR|O_CREAT|O_EXCL, 0666);
  if (shmem_fd != -1) {
    /*
     * This is the first access so size the shared memory, mmap it and initialize the data
     */
    int result = ftruncate(shmem_fd, sizeof(Lps22DeviceData));
    device_data_ = static_cast<Lps22DeviceData*>(mmap(NULL, sizeof(Lps22DeviceData), PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0));

My question is how do I initialize the lps22DeviceData in the mmap ?

It is a data only class.

class Lps22DeviceData {
 public:
  std::recursive_mutex lock_ = {};
  uint64_t read_total_ = 0;
  bool initialized = false;
  int16_t temperature_measurement_ = 0;
  time_point<system_clock> temperature_measurement_system_time_;
  time_point<steady_clock> temperature_measurement_steady_time_;
  milliseconds temperature_response_time;

  int32_t pressure_measurement_ = 0;
  time_point<system_clock> pressure_measurement_system_time_;
  time_point<steady_clock> pressure_measurement_steady_time_;
  milliseconds pressure_response_time;
};

Most of them are simple integers or time values that I can just assign to some initial values. But, I haven't figured out how to get the lock_ initialized.

    device_data_->read_total_ = 0;
    device_data_->initialized = false;
    device_data_->temperature_measurement_ = 0;
    device_data_->temperature_measurement_system_time_ = system_clock::now();
    device_data_->temperature_measurement_steady_time_ = steady_clock::now();
    device_data_->temperature_response_time = milliseconds(0);

    device_data_->pressure_measurement_ = 0;
    device_data_->pressure_measurement_system_time_ = system_clock::now();
    device_data_->pressure_measurement_steady_time_ = steady_clock::now();
    device_data_->pressure_response_time = milliseconds(0);
    device_data_->initialized = true;

I tried:

device_data_->lock_ = {};

Which seems to work in the class definition when I had this working for multiple instances in one process:

[build] /home/chrisk/Projects/RaspberryPi/WS/src/lib/devices/i2c/lps22.cpp: In constructor ‘Lps22::Lps22(I2cBus, uint8_t)’:
[build] /home/chrisk/Projects/RaspberryPi/WS/src/lib/devices/i2c/lps22.cpp:49:28: error: use of deleted function ‘std::recursive_mutex& std::recursive_mutex::operator=(const std::recursive_mutex&)’
[build]    49 |     device_data_->lock_ = {};

How do I initialize a device_data_->lock_ that ends up inside the mmap so that all processes see the lock?

Thanks

8
  • This is not going to be sufficient. Process A checks the lock and sees it can use the device. At the exact same time in another core Process B checks the lock and sees it can use the device. Process A and Process B then both set the flag to prevent further entrants, but you already have one more entrant than is acceptable. You will also have a problem with a process that crashes while the flag is set. Commented Nov 18, 2024 at 20:07
  • pubs.opengroup.org/onlinepubs/009695399/functions/… may be of assistance. Commented Nov 18, 2024 at 20:08
  • I see your points. I did find out about something called a "placement new" that does allow you to define where an object gets defined. So "new (device_data_) LpsDeviceData;" does at least pass the compiler. But I'll have to take your points into consideration. Thanks Commented Nov 18, 2024 at 20:27
  • Also useful to you: Boost Interprocess Commented Nov 18, 2024 at 22:24
  • 1
    Almost everything in Linux is a file, including shared memory. What looks like you need here is a pipe that would pass messages between processes. That's also a file, but it has a mechanism of guaranteeing two point communication without data races. Commented Nov 19, 2024 at 1:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.