예제 #1
0
        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);
 }
예제 #3
0
        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;
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        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();
                        }
                    }
                }
            }
        }
예제 #6
0
 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;
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
            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();
                        }
                    }
                }
            }
예제 #11
0
        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);
        }
예제 #12
0
            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);
                }
            }
예제 #13
0
        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;
        }