9
votes

I have implemented two applications that share data using the POSIX shared memory API (i.e. shm_open). One process updates data stored in the shared memory segment and another process reads it. I want to synchronize the access to the shared memory region using some sort of mutex or semaphore. What is the most efficient way of do this? Some mechanisms I am considering are

  • A POSIX mutex stored in the shared memory segment (Setting the PTHREAD_PROCESS_SHARED attribute would be required)
  • Creating a System V semaphore using semget
4
What programming language ? For C++ consider boost::interprocess. - Paul R
Out of curiosity, why are you using a shared memory segment instead of a named file on a tmpfs or hugetlbfs? I'd probably use a POSIX mutex since they've been very fast for several years on Linux. - tmyklebu
@tmyklebu: I am using shared memory to avoid system calls and unnecessary data copying. After the shared memory segments are setup, the data is accessed by simply using pointers. - waffleman
What unnecessary data copying happens when you create, grow, and mmap() a file on a tmpfs or hugetlbfs? - tmyklebu

4 Answers

4
votes

Rather than a System V semaphore, I would go with a POSIX named semaphore using sem_open(), etc.

2
votes

Might as well make this an answer.

You can use sem_init with pshared true to create a POSIX semaphore in your shared memory space. I have used this successfully in the past.

As for whether this is faster or slower than a shared mutex and condition variable, only profiling can tell you. On Linux I suspect they are all pretty similar since they rely on the "futex" machinery.

0
votes

If efficiency is important, I would go with process-shared mutexes and condition variables.

AFAIR, each operation with a semaphore requires a syscall, so uncontended mutex should be faster than the semaphore [ab]used in mutex-like manner.

0
votes

First, really benchmark to know if performance is important. The cost of these things is often overestimated. So if you don't find that the access to the control structure is of same order of magnitude than the writes, just take whatever construct is semantically the best for your use case. This would be the case usually if you'd have some 100 bytes written per access to the control structure.

Otherwise, if the control structure is the bottleneck, you should perhaps avoid to use them. C11 has the new concept of _Atomic types and operations that can be used in cases where there are races in access to data. C11 is not yet widely implemented but probably all modern compilers have extensions that implement these features already.