public static MemoryMapping Create(string path) { MemoryMappedFile file = null; MemoryMappedViewAccessor accessor = null; SafeMemoryMappedViewHandle handle = null; MemoryMapping mapping = null; FileStream stream = null; byte * ptr = null; try { stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite); file = MemoryMappedFile.CreateFromFile(stream, null, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.None, true); accessor = file.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); mapping = new MemoryMapping(); // we need to make sure that the handle and the acquired pointer get stored to MemoryMapping: RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { handle = accessor.SafeMemoryMappedViewHandle; handle.AcquirePointer(ref ptr); if (ptr == null) { throw new IOException("Cannot create a file mapping"); } mapping._handle = handle; mapping._pointer = ptr; mapping._capacity = accessor.Capacity; } } finally { stream?.Dispose(); accessor?.Dispose(); file?.Dispose(); } return(mapping); }
public MemoryMappedFileMemoryManager(SafeMemoryMappedViewHandle view, int offset, int size) { _view = view; _offset = offset; _size = size; _view.AcquirePointer(ref _pointer); }
public FixedSizeDirectFile(string filePath, int size = 4096) { _filePath = filePath; if (size < 0) { throw new ArgumentOutOfRangeException(nameof(size)); } size = ((size - 1) / 4096 + 1) * 4096; _fileStream = new FileStream(_filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1, FileOptions.None); var bytesCapacity = checked ((int)Math.Max(_fileStream.Length, size)); _mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, bytesCapacity, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, true); _va = _mmf.CreateViewAccessor(0, bytesCapacity, MemoryMappedFileAccess.ReadWrite); _vaHandle = _va.SafeMemoryMappedViewHandle; _vaHandle.AcquirePointer(ref _pointer); _size = bytesCapacity; }
public unsafe void CopyMemoryFromOffset(ulong rva, IntPtr destination, uint size) { try { byte *baseOfView = null; _mappedFileView.AcquirePointer(ref baseOfView); IntPtr readAddress = new IntPtr(baseOfView + rva); windows.RtlMoveMemory(destination, readAddress, new IntPtr(size)); } finally { _mappedFileView.ReleasePointer(); } }
public void Flush(IntPtr capacity) { if (m_viewHandle != null) { unsafe { byte *firstPagePtr = null; RuntimeHelpers.PrepareConstrainedRegions(); try { m_viewHandle.AcquirePointer(ref firstPagePtr); bool success = UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity); if (success) { return; // This will visit the finally block. } // It is a known issue within the NTFS transaction log system that // causes FlushViewOfFile to intermittently fail with ERROR_LOCK_VIOLATION // [http://bugcheck/bugs/Windows8Bugs/152862]. // As a workaround, we catch this particular error and retry the flush operation // a few milliseconds later. If it does not work, we give it a few more tries with // increasing intervals. Eventually, however, we need to give up. In ad-hoc tests // this strategy successfully flushed the view after no more than 3 retries. Int32 error = Marshal.GetLastWin32Error(); bool canRetry = (!success && error == UnsafeNativeMethods.ERROR_LOCK_VIOLATION); for (Int32 w = 0; canRetry && w < MaxFlushWaits; w++) { Int32 pause = (1 << w); // MaxFlushRetries should never be over 30 Thread.Sleep(pause); for (Int32 r = 0; canRetry && r < MaxFlushRetriesPerWait; r++) { success = UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity); if (success) { return; // This will visit the finally block. } Thread.Sleep(0); error = Marshal.GetLastWin32Error(); canRetry = (error == UnsafeNativeMethods.ERROR_LOCK_VIOLATION); } } // We got too here, so there was no success: __Error.WinIOError(error, String.Empty); } finally { if (firstPagePtr != null) { m_viewHandle.ReleasePointer(); } } } } }
public unsafe override Span <byte> GetSpan() { unsafe { byte *ptrMemMap = (byte *)0; mma.AcquirePointer(ref ptrMemMap); return(new Span <byte>(ptrMemMap, (int)mma.ByteLength)); } }
private Win32MemoryMappedFile(FileStream fs, SafeMemoryMappedFileHandle handle, ulong size) { Contract.Requires(fs != null && handle != null && !handle.IsInvalid && !handle.IsClosed); m_mapHandle = handle; m_file = fs; m_size = size; // verify that it fits on 32 bit OS... if (IntPtr.Size == 4 && size > uint.MaxValue) { // won't work with 32-bit pointers throw new InvalidOperationException("Memory mapped file size is too big to be opened on a 32-bit system."); } // verifiy that it will fit in the virtual address space of the process var totalVirtual = UnsafeNativeMethods.GetTotalVirtualAddressSpaceSize(); if (size > totalVirtual) { throw new InvalidOperationException("Memory mapped file size is too big to fit in the current process virtual address space"); } SafeMemoryMappedViewHandle view = null; byte *baseAddress = null; try { view = UnsafeNativeMethods.MapViewOfFile(m_mapHandle, UnsafeNativeMethods.FileMapAccess.FileMapRead, 0, 0, new UIntPtr(size)); if (view.IsInvalid) { throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); } view.Initialize(size); m_viewHandle = view; view.AcquirePointer(ref baseAddress); m_baseAddress = baseAddress; } catch { if (baseAddress != null) { view.ReleasePointer(); } if (view != null) { view.Dispose(); } m_file = null; m_viewHandle = null; m_mapHandle = null; m_baseAddress = null; throw; } }
public unsafe int Read(byte[] buffer, int offset, int count) { long position = _position + _origin; long numOfBytesToRead = _length - position; if (numOfBytesToRead > count) { numOfBytesToRead = count; } if (numOfBytesToRead <= 0) { return(0); } byte *pointer = null; RuntimeHelpers.PrepareConstrainedRegions(); try { _buffer.AcquirePointer(ref pointer); BufferUtils.Memcpy((byte *)(pointer + position), 0, buffer, offset, count); } finally { if (pointer != null) { _buffer.ReleasePointer(); } } _position += count; return(count); }
public ReadOnlySpan <byte> ReadSpan() { va = mm.CreateViewStream(); mma = va.SafeMemoryMappedViewHandle; ReadOnlySpan <byte> bytes; unsafe { byte *ptrMemMap = (byte *)0; mma.AcquirePointer(ref ptrMemMap); bytes = new ReadOnlySpan <byte>(ptrMemMap, (int)mma.ByteLength); mma.ReleasePointer(); } return(bytes); }
public override unsafe int Read(TiffStreamOffset offset, Memory <byte> buffer) { MemoryMappedFile?file = Volatile.Read(ref _file); if (file is null) { throw new ObjectDisposedException(nameof(ContentReader)); } if (offset.Offset + buffer.Length > _capacity) { buffer = buffer.Slice(0, Math.Max(0, (int)(_capacity - offset.Offset))); } if (buffer.IsEmpty) { return(0); } using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor(offset, 0, MemoryMappedFileAccess.Read)) { byte *pointer = null; SafeMemoryMappedViewHandle handle = accessor.SafeMemoryMappedViewHandle; #if !NETSTANDARD1_3 System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); #endif try { handle.AcquirePointer(ref pointer); if (pointer != null) { new Span <byte>(pointer + accessor.PointerOffset, buffer.Length).CopyTo(buffer.Span); } return(buffer.Length); } finally { if (pointer != null) { handle.ReleasePointer(); } } } }
public bool Open(string path, bool isReadOnly) { Close(); FileAccess fileAccess = isReadOnly ? FileAccess.Read : FileAccess.ReadWrite; MemoryMappedFileAccess memoryMappedFileAccess = isReadOnly ? MemoryMappedFileAccess.Read : MemoryMappedFileAccess.ReadWrite; var tmpFileName = Path.GetFileName(path); fs = new FileStream(path, FileMode.Open, fileAccess, FileShare.Read); mmf = MemoryMappedFile.CreateFromFile( fs, tmpFileName, 0, memoryMappedFileAccess, HandleInheritability.None, true); mmva = mmf.CreateViewAccessor(0, 0, memoryMappedFileAccess); smmv = mmva.SafeMemoryMappedViewHandle; bool result = false; unsafe { byte *pointer = null; smmv.AcquirePointer(ref pointer); if (pointer == null) { throw new FileLoadException("无法载入文件"); } pe = new PeImage(pointer, false); result = true; } if (result) { fileName = tmpFileName; OnEventNotify(Opened); } else { fileName = string.Empty; throw new InvalidDataException("不是PE文件"); } return(result); }
public CopiedMemoryMappedViewHandle(SafeMemoryMappedViewHandle viewHandle) { _viewHandle = viewHandle; byte *pointer = null; // The following code uses a constrained execution region (CER) to ensure that the code ends up in one // of the following states, even in the presence of asynchronous exceptions like ThreadAbortException: // // 1. The pointer is not acquired, and the current handle is invalid (thus will not be released) // 2. The pointer is acquired, and the current handle is fully initialized for later cleanup RuntimeHelpers.PrepareConstrainedRegions(); try { viewHandle.AcquirePointer(ref pointer); } finally { SetHandle((IntPtr)pointer); } }
internal void Grow(long minCapacity, bool sparse = false) { if (minCapacity < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(nameof(minCapacity)); } if (_isWritable) { minCapacity = ((minCapacity - 1) / 4096 + 1) * 4096; } if (_fileStream == null) { // NB No need to recreate file // If capacity is larger than the size of the file on disk, the file on disk is // increased to match the specified capacity even if no data is written to the // memory-mapped file. To prevent this from occurring, specify 0 (zero) for the // default capacity, which will internally set capacity to the size of the file on disk. //var handle = Mono.Posix.Syscall.open(_filePath, (Mono.Posix.OpenFlags) (0)); // _isWritable // //? Mono.Posix.OpenFlags.O_RDWR //| Mono.Posix.OpenFlags.O_CREAT // //: Mono.Posix.OpenFlags.O_RDONLY); //, FileMode.S_IWUSR | FileMode.S_IRUSR | FileMode.S_IROTH | FileMode.S_IWOTH); //var sfh = new SafeFileHandle((IntPtr)handle, true); //_fileStream = new FileStream(sfh, _isWritable ? FileAccess.ReadWrite : FileAccess.Read, 1, false); _fileStream = new FileStream(_filePath, _isWritable ? FileMode.OpenOrCreate : FileMode.Open, _isWritable ? FileAccess.ReadWrite : FileAccess.Read, FileShare.ReadWrite, 1, _fileOptions); if (sparse) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (!MarkAsSparseFile(_fileStream)) { throw new Win32Exception("Cannot make a sparse file."); } } else { // We allocate in chunks of 64-128 MB, not a big deal for servers // Need this for MacOS, it's not nice to have pre-allocated 1 GB // just in case. Trace.TraceWarning("Sparse files not implemented on non-Windows"); } } if (!_isWritable && _fileStream.Length == 0) { _fileStream.Dispose(); _fileStream = null; ThrowHelper.ThrowInvalidOperationException($"File {_filePath} is empty. Cannot open DirectFile in read-only mode."); return; } } else if (_isWritable) { // _va.Dispose does this // Flush(flushToDisk); } if (!_isWritable && minCapacity > _fileStream.Length) { ThrowHelper.ThrowArgumentException("minCapacity > _fileStream.Length"); } // NB another thread could have increased the map size and _capacity could be stale var bytesCapacity = Math.Max(_fileStream.Length, minCapacity); _va?.Flush(); _vaHandle?.ReleasePointer(); _vaHandle?.Dispose(); _va?.Dispose(); _mmf?.Dispose(); // var unique = ((long)Process.GetCurrentProcess().Id << 32) | _counter++; // NB: map name must be unique var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, // $@"{Path.GetFileName(_filePath)}.{unique}" bytesCapacity, _isWritable ? MemoryMappedFileAccess.ReadWrite : MemoryMappedFileAccess.Read, HandleInheritability.None, true); _mmf = mmf; byte *ptr = (byte *)0; _va = _mmf.CreateViewAccessor(0, bytesCapacity, _isWritable ? MemoryMappedFileAccess.ReadWrite : MemoryMappedFileAccess.Read); _vaHandle = _va.SafeMemoryMappedViewHandle; _vaHandle.AcquirePointer(ref ptr); _pointer = ptr; _capacity = bytesCapacity; }