Реализация syscall.Mmap - PullRequest
       13

Реализация syscall.Mmap

1 голос
/ 21 февраля 2020

Исходный код здесь

Я прокомментировал то, что понимаю

type mmapper struct {
    sync.Mutex
    active map[*byte][]byte // active mappings; key is last byte in mapping
    mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
    munmap func(addr uintptr, length uintptr) error
}

func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
    if length <= 0 {
        return nil, EINVAL
    }

    // Map the requested memory using a operating-system dependent function
    addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
    if errno != nil {
        return nil, errno
    }

    // Create slice memory layout
    var sl = struct {
        addr uintptr
        len  int
        cap  int
    }{addr, length, length}

    // Cast it to byte slice
    b := *(*[]byte)(unsafe.Pointer(&sl))

    // ??
    p := &b[cap(b)-1]
    m.Lock()
    defer m.Unlock()
    m.active[p] = b
    return b, nil
}

func (m *mmapper) Munmap(data []byte) (err error) {
    if len(data) == 0 || len(data) != cap(data) {
        return EINVAL
    }

    // Check if the slice is valid ?
    p := &data[cap(data)-1]
    m.Lock()
    defer m.Unlock()
    b := m.active[p]
    if b == nil || &b[0] != &data[0] {
        return EINVAL
    }

    // Unmap the memory and update m.
    if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
        return errno
    }
    delete(m.active, p)
    return nil
}

Так что мой вопрос только о поле mmapper.active, я не не понимаю, для чего это.

Я читал о некоторых проблемах с uintptr и сборщиком мусора, может быть, для их предотвращения? Или, может быть, это просто для проверки среза, когда Munmap это вызов?

1 Ответ

0 голосов
/ 21 февраля 2020

Это может быть срез среза, тогда его обратный указатель будет отличаться от оригинала. Эта карта позволяет нам проверить, был ли этот срез нарезан.

b := []byte{1,2,3,4}

fmt.Println(&b[0]) // 0x40e020

b = b[1:]

fmt.Println(&b[0]) // 0x40e021

https://play.golang.org/p/WJogLiMOfj7

...