You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mmap.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright 2011 Evan Shaw. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // This file defines the common package interface and contains a little bit of
  5. // factored out logic.
  6. // Package mmap allows mapping files into memory. It tries to provide a simple, reasonably portable interface,
  7. // but doesn't go out of its way to abstract away every little platform detail.
  8. // This specifically means:
  9. // * forked processes may or may not inherit mappings
  10. // * a file's timestamp may or may not be updated by writes through mappings
  11. // * specifying a size larger than the file's actual size can increase the file's size
  12. // * If the mapped file is being modified by another process while your program's running, don't expect consistent results between platforms
  13. package mmap
  14. import (
  15. "errors"
  16. "os"
  17. "reflect"
  18. "unsafe"
  19. )
  20. const (
  21. // RDONLY maps the memory read-only.
  22. // Attempts to write to the MMap object will result in undefined behavior.
  23. RDONLY = 0
  24. // RDWR maps the memory as read-write. Writes to the MMap object will update the
  25. // underlying file.
  26. RDWR = 1 << iota
  27. // COPY maps the memory as copy-on-write. Writes to the MMap object will affect
  28. // memory, but the underlying file will remain unchanged.
  29. COPY
  30. // If EXEC is set, the mapped memory is marked as executable.
  31. EXEC
  32. )
  33. const (
  34. // If the ANON flag is set, the mapped memory will not be backed by a file.
  35. ANON = 1 << iota
  36. )
  37. // MMap represents a file mapped into memory.
  38. type MMap []byte
  39. // Map maps an entire file into memory.
  40. // If ANON is set in flags, f is ignored.
  41. func Map(f *os.File, prot, flags int) (MMap, error) {
  42. return MapRegion(f, -1, prot, flags, 0)
  43. }
  44. // MapRegion maps part of a file into memory.
  45. // The offset parameter must be a multiple of the system's page size.
  46. // If length < 0, the entire file will be mapped.
  47. // If ANON is set in flags, f is ignored.
  48. func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) {
  49. if offset%int64(os.Getpagesize()) != 0 {
  50. return nil, errors.New("offset parameter must be a multiple of the system's page size")
  51. }
  52. var fd uintptr
  53. if flags&ANON == 0 {
  54. fd = uintptr(f.Fd())
  55. if length < 0 {
  56. fi, err := f.Stat()
  57. if err != nil {
  58. return nil, err
  59. }
  60. length = int(fi.Size())
  61. }
  62. } else {
  63. if length <= 0 {
  64. return nil, errors.New("anonymous mapping requires non-zero length")
  65. }
  66. fd = ^uintptr(0)
  67. }
  68. return mmap(length, uintptr(prot), uintptr(flags), fd, offset)
  69. }
  70. func (m *MMap) header() *reflect.SliceHeader {
  71. return (*reflect.SliceHeader)(unsafe.Pointer(m))
  72. }
  73. func (m *MMap) addrLen() (uintptr, uintptr) {
  74. header := m.header()
  75. return header.Data, uintptr(header.Len)
  76. }
  77. // Lock keeps the mapped region in physical memory, ensuring that it will not be
  78. // swapped out.
  79. func (m MMap) Lock() error {
  80. return m.lock()
  81. }
  82. // Unlock reverses the effect of Lock, allowing the mapped region to potentially
  83. // be swapped out.
  84. // If m is already unlocked, aan error will result.
  85. func (m MMap) Unlock() error {
  86. return m.unlock()
  87. }
  88. // Flush synchronizes the mapping's contents to the file's contents on disk.
  89. func (m MMap) Flush() error {
  90. return m.flush()
  91. }
  92. // Unmap deletes the memory mapped region, flushes any remaining changes, and sets
  93. // m to nil.
  94. // Trying to read or write any remaining references to m after Unmap is called will
  95. // result in undefined behavior.
  96. // Unmap should only be called on the slice value that was originally returned from
  97. // a call to Map. Calling Unmap on a derived slice may cause errors.
  98. func (m *MMap) Unmap() error {
  99. err := m.unmap()
  100. *m = nil
  101. return err
  102. }