Home | History | Annotate | Download | only in memory
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MEMORY_SHARED_MEMORY_H_
      6 #define BASE_MEMORY_SHARED_MEMORY_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include <string>
     11 
     12 #include "base/base_export.h"
     13 #include "base/macros.h"
     14 #include "base/memory/shared_memory_handle.h"
     15 #include "base/process/process_handle.h"
     16 #include "build/build_config.h"
     17 
     18 #if defined(OS_POSIX)
     19 #include <stdio.h>
     20 #include <sys/types.h>
     21 #include <semaphore.h>
     22 #include "base/file_descriptor_posix.h"
     23 #include "base/files/file_util.h"
     24 #include "base/files/scoped_file.h"
     25 #endif
     26 
     27 #if defined(OS_WIN)
     28 #include "base/win/scoped_handle.h"
     29 #endif
     30 
     31 namespace base {
     32 
     33 class FilePath;
     34 
     35 // Options for creating a shared memory object.
     36 struct BASE_EXPORT SharedMemoryCreateOptions {
     37 #if defined(OS_MACOSX) && !defined(OS_IOS)
     38   // The type of OS primitive that should back the SharedMemory object.
     39   SharedMemoryHandle::Type type = SharedMemoryHandle::MACH;
     40 #else
     41   // DEPRECATED (crbug.com/345734):
     42   // If NULL, the object is anonymous.  This pointer is owned by the caller
     43   // and must live through the call to Create().
     44   const std::string* name_deprecated = nullptr;
     45 
     46   // DEPRECATED (crbug.com/345734):
     47   // If true, and the shared memory already exists, Create() will open the
     48   // existing shared memory and ignore the size parameter.  If false,
     49   // shared memory must not exist.  This flag is meaningless unless
     50   // name_deprecated is non-NULL.
     51   bool open_existing_deprecated = false;
     52 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
     53 
     54   // Size of the shared memory object to be created.
     55   // When opening an existing object, this has no effect.
     56   size_t size = 0;
     57 
     58   // If true, mappings might need to be made executable later.
     59   bool executable = false;
     60 
     61   // If true, the file can be shared read-only to a process.
     62   bool share_read_only = false;
     63 };
     64 
     65 // Platform abstraction for shared memory.  Provides a C++ wrapper
     66 // around the OS primitive for a memory mapped file.
     67 class BASE_EXPORT SharedMemory {
     68  public:
     69   SharedMemory();
     70 
     71 #if defined(OS_WIN)
     72   // Similar to the default constructor, except that this allows for
     73   // calling LockDeprecated() to acquire the named mutex before either Create or
     74   // Open are called on Windows.
     75   explicit SharedMemory(const std::wstring& name);
     76 #endif
     77 
     78   // Create a new SharedMemory object from an existing, open
     79   // shared memory file.
     80   //
     81   // WARNING: This does not reduce the OS-level permissions on the handle; it
     82   // only affects how the SharedMemory will be mmapped.  Use
     83   // ShareReadOnlyToProcess to drop permissions.  TODO(jln,jyasskin): DCHECK
     84   // that |read_only| matches the permissions of the handle.
     85   SharedMemory(const SharedMemoryHandle& handle, bool read_only);
     86 
     87   // Closes any open files.
     88   ~SharedMemory();
     89 
     90   // Return true iff the given handle is valid (i.e. not the distingished
     91   // invalid value; NULL for a HANDLE and -1 for a file descriptor)
     92   static bool IsHandleValid(const SharedMemoryHandle& handle);
     93 
     94   // Returns invalid handle (see comment above for exact definition).
     95   static SharedMemoryHandle NULLHandle();
     96 
     97   // Closes a shared memory handle.
     98   static void CloseHandle(const SharedMemoryHandle& handle);
     99 
    100   // Returns the maximum number of handles that can be open at once per process.
    101   static size_t GetHandleLimit();
    102 
    103   // Duplicates The underlying OS primitive. Returns NULLHandle() on failure.
    104   // The caller is responsible for destroying the duplicated OS primitive.
    105   static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle);
    106 
    107 #if defined(OS_POSIX)
    108   // This method requires that the SharedMemoryHandle is backed by a POSIX fd.
    109   static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle);
    110 #endif
    111 
    112 #if defined(OS_POSIX) && !defined(OS_ANDROID)
    113   // Gets the size of the shared memory region referred to by |handle|.
    114   // Returns false on a failure to determine the size. On success, populates the
    115   // output variable |size|.
    116   static bool GetSizeFromSharedMemoryHandle(const SharedMemoryHandle& handle,
    117                                             size_t* size);
    118 #endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
    119 
    120   // Creates a shared memory object as described by the options struct.
    121   // Returns true on success and false on failure.
    122   bool Create(const SharedMemoryCreateOptions& options);
    123 
    124   // Creates and maps an anonymous shared memory segment of size size.
    125   // Returns true on success and false on failure.
    126   bool CreateAndMapAnonymous(size_t size);
    127 
    128   // Creates an anonymous shared memory segment of size size.
    129   // Returns true on success and false on failure.
    130   bool CreateAnonymous(size_t size) {
    131     SharedMemoryCreateOptions options;
    132     options.size = size;
    133     return Create(options);
    134   }
    135 
    136 #if !defined(OS_MACOSX) || defined(OS_IOS)
    137   // DEPRECATED (crbug.com/345734):
    138   // Creates or opens a shared memory segment based on a name.
    139   // If open_existing is true, and the shared memory already exists,
    140   // opens the existing shared memory and ignores the size parameter.
    141   // If open_existing is false, shared memory must not exist.
    142   // size is the size of the block to be created.
    143   // Returns true on success, false on failure.
    144   bool CreateNamedDeprecated(
    145       const std::string& name, bool open_existing, size_t size) {
    146     SharedMemoryCreateOptions options;
    147     options.name_deprecated = &name;
    148     options.open_existing_deprecated = open_existing;
    149     options.size = size;
    150     return Create(options);
    151   }
    152 
    153   // Deletes resources associated with a shared memory segment based on name.
    154   // Not all platforms require this call.
    155   bool Delete(const std::string& name);
    156 
    157   // Opens a shared memory segment based on a name.
    158   // If read_only is true, opens for read-only access.
    159   // Returns true on success, false on failure.
    160   bool Open(const std::string& name, bool read_only);
    161 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
    162 
    163   // Maps the shared memory into the caller's address space.
    164   // Returns true on success, false otherwise.  The memory address
    165   // is accessed via the memory() accessor.  The mapped address is guaranteed to
    166   // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail
    167   // if this object is currently mapped.
    168   bool Map(size_t bytes) {
    169     return MapAt(0, bytes);
    170   }
    171 
    172   // Same as above, but with |offset| to specify from begining of the shared
    173   // memory block to map.
    174   // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|.
    175   bool MapAt(off_t offset, size_t bytes);
    176   enum { MAP_MINIMUM_ALIGNMENT = 32 };
    177 
    178   // Unmaps the shared memory from the caller's address space.
    179   // Returns true if successful; returns false on error or if the
    180   // memory is not mapped.
    181   bool Unmap();
    182 
    183   // The size requested when the map is first created.
    184   size_t requested_size() const { return requested_size_; }
    185 
    186   // The actual size of the mapped memory (may be larger than requested).
    187   size_t mapped_size() const { return mapped_size_; }
    188 
    189   // Gets a pointer to the opened memory space if it has been
    190   // Mapped via Map().  Returns NULL if it is not mapped.
    191   void* memory() const { return memory_; }
    192 
    193   // Returns the underlying OS handle for this segment.
    194   // Use of this handle for anything other than an opaque
    195   // identifier is not portable.
    196   SharedMemoryHandle handle() const;
    197 
    198   // Returns the underlying OS handle for this segment. The caller also gets
    199   // ownership of the handle. This is logically equivalent to:
    200   //   SharedMemoryHandle dup = DuplicateHandle(handle());
    201   //   Close();
    202   //   return dup;
    203   SharedMemoryHandle TakeHandle();
    204 
    205   // Closes the open shared memory segment. The memory will remain mapped if
    206   // it was previously mapped.
    207   // It is safe to call Close repeatedly.
    208   void Close();
    209 
    210   // Shares the shared memory to another process.  Attempts to create a
    211   // platform-specific new_handle which can be used in a remote process to read
    212   // the shared memory file.  new_handle is an output parameter to receive the
    213   // handle for use in the remote process.
    214   //
    215   // |*this| must have been initialized using one of the Create*() or Open()
    216   // methods with share_read_only=true. If it was constructed from a
    217   // SharedMemoryHandle, this call will CHECK-fail.
    218   //
    219   // Returns true on success, false otherwise.
    220   bool ShareReadOnlyToProcess(ProcessHandle process,
    221                               SharedMemoryHandle* new_handle) {
    222     return ShareToProcessCommon(process, new_handle, false, SHARE_READONLY);
    223   }
    224 
    225   // Logically equivalent to:
    226   //   bool ok = ShareReadOnlyToProcess(process, new_handle);
    227   //   Close();
    228   //   return ok;
    229   // Note that the memory is unmapped by calling this method, regardless of the
    230   // return value.
    231   bool GiveReadOnlyToProcess(ProcessHandle process,
    232                              SharedMemoryHandle* new_handle) {
    233     return ShareToProcessCommon(process, new_handle, true, SHARE_READONLY);
    234   }
    235 
    236   // Shares the shared memory to another process.  Attempts
    237   // to create a platform-specific new_handle which can be
    238   // used in a remote process to access the shared memory
    239   // file.  new_handle is an output parameter to receive
    240   // the handle for use in the remote process.
    241   // Returns true on success, false otherwise.
    242   bool ShareToProcess(ProcessHandle process,
    243                       SharedMemoryHandle* new_handle) {
    244     return ShareToProcessCommon(process, new_handle, false, SHARE_CURRENT_MODE);
    245   }
    246 
    247   // Logically equivalent to:
    248   //   bool ok = ShareToProcess(process, new_handle);
    249   //   Close();
    250   //   return ok;
    251   // Note that the memory is unmapped by calling this method, regardless of the
    252   // return value.
    253   bool GiveToProcess(ProcessHandle process,
    254                      SharedMemoryHandle* new_handle) {
    255     return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE);
    256   }
    257 
    258 #if defined(OS_POSIX) && (!defined(OS_MACOSX) || defined(OS_IOS)) && \
    259     !defined(OS_NACL)
    260   using UniqueId = std::pair<dev_t, ino_t>;
    261 
    262   struct UniqueIdHash {
    263     size_t operator()(const UniqueId& id) const {
    264       return HashInts(id.first, id.second);
    265     }
    266   };
    267 
    268   // Returns a unique ID for this shared memory's handle. Note this function may
    269   // access file system and be slow.
    270   bool GetUniqueId(UniqueId* id) const;
    271 #endif
    272 
    273  private:
    274 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \
    275     (!defined(OS_MACOSX) || defined(OS_IOS))
    276   bool FilePathForMemoryName(const std::string& mem_name, FilePath* path);
    277 #endif
    278 
    279   enum ShareMode {
    280     SHARE_READONLY,
    281     SHARE_CURRENT_MODE,
    282   };
    283 
    284 #if defined(OS_MACOSX)
    285   bool Share(SharedMemoryHandle* new_handle, ShareMode share_mode);
    286 #endif
    287 
    288   bool ShareToProcessCommon(ProcessHandle process,
    289                             SharedMemoryHandle* new_handle,
    290                             bool close_self,
    291                             ShareMode);
    292 
    293 #if defined(OS_WIN)
    294   // If true indicates this came from an external source so needs extra checks
    295   // before being mapped.
    296   bool external_section_;
    297   std::wstring       name_;
    298   win::ScopedHandle  mapped_file_;
    299 #elif defined(OS_MACOSX) && !defined(OS_IOS)
    300   // The OS primitive that backs the shared memory region.
    301   SharedMemoryHandle shm_;
    302 
    303   // The mechanism by which the memory is mapped. Only valid if |memory_| is not
    304   // |nullptr|.
    305   SharedMemoryHandle::Type mapped_memory_mechanism_;
    306 
    307   int readonly_mapped_file_;
    308 #elif defined(OS_POSIX)
    309   int                mapped_file_;
    310   int                readonly_mapped_file_;
    311 #endif
    312   size_t             mapped_size_;
    313   void*              memory_;
    314   bool               read_only_;
    315   size_t             requested_size_;
    316 
    317   DISALLOW_COPY_AND_ASSIGN(SharedMemory);
    318 };
    319 
    320 }  // namespace base
    321 
    322 #endif  // BASE_MEMORY_SHARED_MEMORY_H_
    323