SharedMemory

// SharedMemoryHandle is a platform specific type which represents

// the underlying OS handle to a shared memory segment.

#if defined(OS_WIN)

typedef HANDLE SharedMemoryHandle;

typedef HANDLE SharedMemoryLock;

#elif defined(OS_POSIX)

// A SharedMemoryId is sufficient to identify a given shared memory segment on a

// system, but insufficient to map it.

typedef FileDescriptor SharedMemoryHandle;

typedef ino_t SharedMemoryId;

// On POSIX, the lock is implemented as a lockf() on the mapped file,

// so no additional member (or definition of SharedMemoryLock) is

// needed.

#endif

 

// Platform abstraction for shared memory.  Provides a C++ wrapper

// around the OS primitive for a memory mapped file.

class SharedMemory {

 public:

  // Create a new SharedMemory object.

  SharedMemory();

 

  // Create a new SharedMemory object from an existing, open

  // shared memory file.

  SharedMemory(SharedMemoryHandle handle, bool read_only);

 

  // Create a new SharedMemory object from an existing, open

  // shared memory file that was created by a remote process and not shared

  // to the current process.

  SharedMemory(SharedMemoryHandle handle, bool read_only,

      base::ProcessHandle process);

 

  // Destructor.  Will close any open files.

  ~SharedMemory();

 

  // Return true iff the given handle is valid (i.e. not the distingished

  // invalid value; NULL for a HANDLE and -1 for a file descriptor)

  static bool IsHandleValid(const SharedMemoryHandle& handle);

 

  // Return invalid handle (see comment above for exact definition).

  static SharedMemoryHandle NULLHandle();

 

  // Close a shared memory handle.

  static void CloseHandle(const SharedMemoryHandle& handle);

 

  // Creates or opens a shared memory segment based on a name.

  // If read_only is true, opens the memory as read-only.

  // If open_existing is true, and the shared memory already exists,

  // opens the existing shared memory and ignores the size parameter.

  // If name is the empty string, use a unique name.

  // Returns true on success, false on failure.

  bool Create(const std::wstring& name, bool read_only, bool open_existing,

              size_t size);

 

  // Deletes resources associated with a shared memory segment based on name.

  // Not all platforms require this call.

  bool Delete(const std::wstring& name);

 

  // Opens a shared memory segment based on a name.

  // If read_only is true, opens for read-only access.

  // If name is the empty string, use a unique name.

  // Returns true on success, false on failure.

  bool Open(const std::wstring& name, bool read_only);

 

  // Maps the shared memory into the caller's address space.

  // Returns true on success, false otherwise.  The memory address

  // is accessed via the memory() accessor.

  bool Map(size_t bytes);

 

  // Unmaps the shared memory from the caller's address space.

  // Returns true if successful; returns false on error or if the

  // memory is not mapped.

  bool Unmap();

 

  // Get the size of the opened shared memory backing file.

  // Note:  This size is only available to the creator of the

  // shared memory, and not to those that opened shared memory

  // created externally.

  // Returns 0 if not opened or unknown.

  size_t max_size() const { return max_size_; }

 

  // Gets a pointer to the opened memory space if it has been

  // Mapped via Map().  Returns NULL if it is not mapped.

  void *memory() const { return memory_; }

 

  // Get access to the underlying OS handle for this segment.

  // Use of this handle for anything other than an opaque

  // identifier is not portable.

  SharedMemoryHandle handle() const;

 

#if defined(OS_POSIX)

  // Return a unique identifier for this shared memory segment. Inode numbers

  // are technically only unique to a single filesystem. However, we always

  // allocate shared memory backing files from the same directory, so will end

  // up on the same filesystem.

  SharedMemoryId id() const { return inode_; }

#endif

 

  // Closes the open shared memory segment.

  // It is safe to call Close repeatedly.

  void Close();

 

  // Share the shared memory to another process.  Attempts

  // to create a platform-specific new_handle which can be

  // used in a remote process to access the shared memory

  // file.  new_handle is an ouput parameter to receive

  // the handle for use in the remote process.

  // Returns true on success, false otherwise.

  bool ShareToProcess(base::ProcessHandle process,

                      SharedMemoryHandle* new_handle) {

    return ShareToProcessCommon(process, new_handle, false);

  }

 

  // Logically equivalent to:

  //   bool ok = ShareToProcess(process, new_handle);

  //   Close();

  //   return ok;

  // Note that the memory is unmapped by calling this method, regardless of the

  // return value.

  bool GiveToProcess(ProcessHandle process,

                     SharedMemoryHandle* new_handle) {

    return ShareToProcessCommon(process, new_handle, true);

  }

 

  // Lock the shared memory.

  // This is a cross-process lock which may be recursively

  // locked by the same thread.

  // TODO(port):

  // WARNING: on POSIX the lock only works across processes, not

  // across threads.  2 threads in the same process can both grab the

  // lock at the same time.  There are several solutions for this

  // (futex, lockf+anon_semaphore) but none are both clean and common

  // across Mac and Linux.

  void Lock();

 

  // Release the shared memory lock.

  void Unlock();

 

 private:

#if defined(OS_POSIX)

  bool CreateOrOpen(const std::wstring &name, int posix_flags, size_t size);

  bool FilenameForMemoryName(const std::wstring &memname,

                             std::wstring *filename);

  void LockOrUnlockCommon(int function);

 

#endif

  bool ShareToProcessCommon(ProcessHandle process,

                            SharedMemoryHandle* new_handle,

                            bool close_self);

 

#if defined(OS_WIN)

  std::wstring       name_;

  HANDLE             mapped_file_;

#elif defined(OS_POSIX)

  int                mapped_file_;

  ino_t              inode_;

#endif

  void*              memory_;

  bool               read_only_;

  size_t             max_size_;

#if !defined(OS_POSIX)

  SharedMemoryLock   lock_;

#endif

 

  DISALLOW_EVIL_CONSTRUCTORS(SharedMemory);

};

SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
                           ProcessHandle process)
    : mapped_file_(NULL),
      memory_(NULL),
      read_only_(read_only),
      max_size_(0),
      lock_(NULL) {
  ::DuplicateHandle(process, handle,
                    GetCurrentProcess(), &mapped_file_,
                    STANDARD_RIGHTS_REQUIRED |
                    (read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS),
                    FALSE, 0);
}
SharedMemory::~SharedMemory() {
  Close();
  if (lock_ != NULL)
    CloseHandle(lock_);
}
// static
bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
  return handle != NULL;
}
// static
SharedMemoryHandle SharedMemory::NULLHandle() {
  return NULL;
}
// static
void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
  DCHECK(handle != NULL);
  ::CloseHandle(handle);
}
bool SharedMemory::Create(const std::wstring &name, bool read_only,
                          bool open_existing, size_t size) {
  DCHECK(mapped_file_ == NULL);
  name_ = name;
  read_only_ = read_only;
  mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
      read_only_ ? PAGE_READONLY : PAGE_READWRITE, 0, static_cast<DWORD>(size),
      name.empty() ? NULL : name.c_str());
  if (!mapped_file_)
    return false;
  // Check if the shared memory pre-exists.
  if (GetLastError() == ERROR_ALREADY_EXISTS && !open_existing) {
    Close();
    return false;
  }
  max_size_ = size;
  return true;
}
bool SharedMemory::Delete(const std::wstring& name) {
  // intentionally empty -- there is nothing for us to do on Windows.
  return true;
}
bool SharedMemory::Open(const std::wstring &name, bool read_only) {
  DCHECK(mapped_file_ == NULL);
  name_ = name;
  read_only_ = read_only;
  mapped_file_ = OpenFileMapping(
      read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, false,
      name.empty() ? NULL : name.c_str());
  if (mapped_file_ != NULL) {
    // Note: size_ is not set in this case.
    return true;
  }
  return false;
}
bool SharedMemory::Map(size_t bytes) {
  if (mapped_file_ == NULL)
    return false;
  memory_ = MapViewOfFile(mapped_file_,
      read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, 0, 0, bytes);
  if (memory_ != NULL) {
    return true;
  }
  return false;
}
bool SharedMemory::Unmap() {
  if (memory_ == NULL)
    return false;
  UnmapViewOfFile(memory_);
  memory_ = NULL;
  return true;
}
bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
                                        SharedMemoryHandle *new_handle,
                                        bool close_self) {
  *new_handle = 0;
  DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ;
  DWORD options = 0;
  HANDLE mapped_file = mapped_file_;
  HANDLE result;
  if (!read_only_)
    access |= FILE_MAP_WRITE;
  if (close_self) {
    // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
    options = DUPLICATE_CLOSE_SOURCE;
    mapped_file_ = NULL;
    Unmap();
  }
  if (process == GetCurrentProcess() && close_self) {
    *new_handle = mapped_file;
    return true;
  }
  if (!DuplicateHandle(GetCurrentProcess(), mapped_file, process,
      &result, access, FALSE, options))
    return false;
  *new_handle = result;
  return true;
}
void SharedMemory::Close() {
  if (memory_ != NULL) {
    UnmapViewOfFile(memory_);
    memory_ = NULL;
  }
  if (mapped_file_ != NULL) {
    CloseHandle(mapped_file_);
    mapped_file_ = NULL;
  }
}
void SharedMemory::Lock() {
  if (lock_ == NULL) {
    std::wstring name = name_;
    name.append(L"lock");
    lock_ = CreateMutex(NULL, FALSE, name.c_str());
    DCHECK(lock_ != NULL);
    if (lock_ == NULL) {
      DLOG(ERROR) << "Could not create mutex" << GetLastError();
      return;  // there is nothing good we can do here.
    }
  }
  WaitForSingleObject(lock_, INFINITE);
}
void SharedMemory::Unlock() {
  DCHECK(lock_ != NULL);
  ReleaseMutex(lock_);
}
SharedMemoryHandle SharedMemory::handle() const {
  return mapped_file_;
}
// A helper class that acquires the shared memory lock while
// the SharedMemoryAutoLock is in scope.
class SharedMemoryAutoLock {
 public:
  explicit SharedMemoryAutoLock(SharedMemory* shared_memory)
      : shared_memory_(shared_memory) {
    shared_memory_->Lock();
  }
  ~SharedMemoryAutoLock() {
    shared_memory_->Unlock();
  }
 private:
  SharedMemory* shared_memory_;
  DISALLOW_EVIL_CONSTRUCTORS(SharedMemoryAutoLock);
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C语言中的sharememory(共享内存)是一种在多个进程之间共享内存数据的机制。通过一定的方法,不同进程可以访问和共享同一片物理内存区域,实现了不同进程之间快速,高效的数据共享。 一个进程将某些内存空间标记为共享,另一个进程通过操作系统的共享内存函数获得对该内存区域的访问权限,进而实现数据的共享。共享内存相较于其他通信机制来说具有快速、高效的优点,因为不需要数据复制和进程切换等操作,数据读取和写入的速度更快,尤其是面对大规模的数据计算和并发问题时,共享内存的表现更加突出。 共享内存也存在一些缺点,主要是由于不同进程可以直接访问同一片内存,因此存在数据一致性和互斥性等问题,需要使用锁和同步机制来避免数据错误和互相影响的问题。共享内存通常应用于高并发场景,如高性能计算、数据库、进程监控和实时系统等。 总之,共享内存是C语言进行多进程间数据共享的重要机制,它提高了数据访问和交互的效率和精准度,也为进程之间相互依赖、协作提供了强有力的支持和保障。 ### 回答2: 共享内存是一种通信方式,它允许不同进程之间共享同一块物理内存空间。采用共享内存进行进程间通信,可以提高程序的运行速度和效率,同时也可以减少进程间通信的复杂度。 在共享内存机制中,多个进程可以同时访问同一块内存区域的数据,而不需要进行数据的复制或传输。这种方法可以避免数据在不同进程之间交换时产生的开销和延迟,从而更快地完成数据共享和协作。 共享内存的实现通常依赖于操作系统提供的特殊机制和标准库。在C语言中,可以使用函数库中的相关API来实现不同进程之间的共享内存交互。例如,在Linux操作系统中,可以使用fork()函数创建新进程,在父/子进程之间共享内存数据,并使用semaphore信号量来进行同步访问。 总的来说,共享内存提供了一种高效、简单和灵活的进程间通信方式。它能够满足不同程序之间的数据交换和协作需求,从而提高程序的性能和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值