boost锁机制中Semaphores的介绍

结构

What's A Semaphore?

  • 旗语是一种基于内部计数的进程间同步机制,它提供了两种基本操作。
  • 等待:测试旗语数的值,如果小于或等于0,则等待,否则递减旗语数。
  • Post:增加旗语数。增加信号量 如果有进程被阻塞,则唤醒其中一个进程。
  • 如果初始旗语数被初始化为1,则Wait操作相当于mutex锁定,Post相当于mutex解锁。这种类型的semaphore被称为二进制semaphore。
  • 虽然旗语可以像mutexes一样使用,但它们有一个独特的特点:与mutexes不同,Post操作不需要由执行Wait操作的同一个线程/进程执行。

Boost.Interprocess Semaphore Types And Headers

  • Boost.Interprocess offers the following semaphore types:
  • #include <boost/interprocess/sync/interprocess_semaphore.hpp>
  • interprocess_semaphore: An anonymous semaphore that can be placed in shared memory or memory mapped files.
  • interprocess_semaphore。一个匿名的信号体,可以放在共享内存或内存映射文件中。
  • #include <boost/interprocess/sync/named_semaphore.hpp>
  • named_semaphore: A named semaphore.
  • named_semaphore。一个命名的旗语。

Anonymous semaphore example

  • We will implement an integer array in shared memory that will be used to transfer data from one process to another process. The first process will write some integers to the array and the process will block if the array is full.
  • The second process will copy the transmitted data to its own buffer, blocking if there is no new data in the buffer.
  • This is the shared integer array (doc_anonymous_semaphore_shared_data.hpp):
  • 我们将在共享内存中实现一个整数数组,用于从一个进程向另一个进程传输数据。第一个进程将向数组写入一些整数,如果数组已满,该进程将阻塞。
  • 第二个进程将把传输的数据复制到自己的缓冲区,如果缓冲区中没有新的数据,则阻塞。
  • 这就是共享整数数组(doc_anonymous_semaphore_shared_data.hpp)。
#include <boost/interprocess/sync/interprocess_semaphore.hpp>

struct shared_memory_buffer
{
   enum { NumItems = 10 };

   shared_memory_buffer()
      : mutex(1), nempty(NumItems), nstored(0)
   {}

   //Semaphores to protect and synchronize access
   boost::interprocess::interprocess_semaphore
      mutex, nempty, nstored;

   //Items to fill
   int items[NumItems];
};
  • 这是进程主进程。创建共享内存,将整数数组放置在那里,并逐个开始整数,如果数组满了,则阻塞。
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"

using namespace boost::interprocess;

int main ()
{
   //Remove shared memory on construction and destruction
   struct shm_remove
   {
      shm_remove() { shared_memory_object::remove("MySharedMemory"); }
      ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
   } remover;

   //Create a shared memory object.
   shared_memory_object shm
      (create_only                  //only create
      ,"MySharedMemory"              //name
      ,read_write  //read-write mode
      );

   //Set size
   shm.truncate(sizeof(shared_memory_buffer));

   //Map the whole shared memory in this process
   mapped_region region
      (shm                       //What to map
      ,read_write //Map it as read-write
      );

   //Get the address of the mapped region
   void * addr       = region.get_address();

   //Construct the shared structure in memory
   shared_memory_buffer * data = new (addr) shared_memory_buffer;

   const int NumMsg = 100;

   //Insert data in the array
   for(int i = 0; i < NumMsg; ++i){
      data->nempty.wait();
      data->mutex.wait();
      data->items[i % shared_memory_buffer::NumItems] = i;
      data->mutex.post();
      data->nstored.post();
   }

   return 0;
}

The second process opens the shared memory and copies the received integers to it's own buffer:

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"

using namespace boost::interprocess;

int main ()
{
   //Remove shared memory on destruction
   struct shm_remove
   {
      ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
   } remover;

   //Create a shared memory object.
   shared_memory_object shm
      (open_only                    //only create
      ,"MySharedMemory"              //name
      ,read_write  //read-write mode
      );

   //Map the whole shared memory in this process
   mapped_region region
      (shm                       //What to map
      ,read_write //Map it as read-write
      );

   //Get the address of the mapped region
   void * addr       = region.get_address();

   //Obtain the shared structure
   shared_memory_buffer * data = static_cast<shared_memory_buffer*>(addr);

   const int NumMsg = 100;

   int extracted_data [NumMsg];

   //Extract the data
   for(int i = 0; i < NumMsg; ++i){
      data->nstored.wait();
      data->mutex.wait();
      extracted_data[i] = data->items[i % shared_memory_buffer::NumItems];
      data->mutex.post();
      data->nempty.post();
   }
   return 0;
}
  • The same interprocess communication can be achieved with a condition variables and mutexes, but for several synchronization patterns, a semaphore is more efficient than a mutex/condition combination.
  • 同样的进程间通信可以用条件变量和mutexes来实现,但对于几种同步模式,semaphore比mutex/条件组合更有效率。

猜你喜欢

转载自blog.csdn.net/CHYabc123456hh/article/details/111412036