Skip to content

ro-ag/posix

Repository files navigation

Posix

This package contains the necessary functions for POSIX shared memory management, Linux and MacOSx The POSIX shared memory API allows processes to communicate information by sharing a region of memory.

Golang doesn't have shm_open implementation and Mmap is not exposing the address parameter, needed for cross programming maps.

I highly recommend to use golang.org/x/sys (which this code is base from) if you don't require mmap with fixed memory address or shm_open function.

According to the Linux manual this package contains the following functions.

  • ShmOpen Create and open a new object, or open an existing object. The call returns a file descriptor for use by the other interfaces listed below.

  • Ftruncate Set the size of the shared memory object. (A newly created shared memory object has a length of zero.)

  • Mmap Map the shared memory object into the virtual address space of the calling process.

  • Munmap Unmap the shared memory object from the virtual address space of the calling process.

  • ShmUnlink Remove a shared memory object name.

  • Close Close the file descriptor allocated by shm_open(3) when it is no longer needed.

  • Fstat Obtain a stat structure that describes the shared memory object. Among the information returned by this call are the object's size (st_size), permissions (st_mode), owner (st_uid), and group (st_gid).

  • Fchown To change the ownership of a shared memory object.

  • Fchmod To change the permissions of a shared memory object.

  • MemfdCreate This function is available since Linux 3.17, basically creates an anonymous memory file descriptor.

Example

host

package main

import (
  "fmt"
  "gopkg.in/ro-ag/posix.v1"
  "log"
  "syscall"
  "unsafe"
)

const AppAddress uintptr = 0x20000000000 // Approximated Address 

type Head struct {
  Addr     unsafe.Pointer
  MemSize  uintptr
  TextSize uintptr
  TextPtr  unsafe.Pointer
}

type Holder struct {
  *Head
  Data []byte
}

func main() {
  // Create File Descriptor	
  fd, err := posix.MemfdCreate("From-Main", posix.MFD_ALLOW_SEALING)
  CheckErr(err)
  // Truncate File max len
  MemSize := posix.Getpagesize() * 4
  err = posix.Ftruncate(fd, MemSize)
  CheckErr(err)

  // mmap returns the map address from system call, 
  // because is not MAP_FIXED will return the closest memory if the address segment is used

  buf, addr, err := posix.Mmap(unsafe.Pointer(AppAddress), MemSize, posix.PROT_WRITE, posix.MAP_SHARED, fd, 0)
  CheckErr(err)

  text := "This works as Mmap in C"
  offset := unsafe.Sizeof(Head{})

  // Unsafe Structure, Easy for writing pointers
  hdr := (*Head)(unsafe.Pointer(&buf[0]))
  hdr.Addr = unsafe.Pointer(addr)
  hdr.MemSize = uintptr(MemSize)
  hdr.TextSize = uintptr(len(text))
  hdr.TextPtr = unsafe.Pointer(&buf[offset])

  holder := &Holder{
    Head: hdr,
    Data: unsafe.Slice(&buf[offset], uintptr(len(text))),
  }

  fmt.Println(holder)

  // Detailed code under ./example folder 

  CheckErr(posix.Munmap(buf)) // unmap memory
  CheckErr(posix.Close(fd))   // close anonymous file

}

// CheckErr wraps around error
func CheckErr(err error) {
  if err != nil {
    no := err.(syscall.Errno)
    log.Fatalf("%s(%d): %v, msg: %s\nhelp: %s", posix.ErrnoName(no), no, err, posix.ErrnoString(no), posix.ErrnoHelp(no))
  }
}

About

memory management Posix

Resources

License

Stars

Watchers

Forks

Packages

No packages published