gopkg.in/ro-ag/posix.v1@v1.0.6/example/host.go (about)

     1  package main
     2  
     3  import (
     4  	"gopkg.in/ro-ag/posix.v1"
     5  	"log"
     6  	"os"
     7  	"os/exec"
     8  	"strings"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  const ApproximatedAddress uintptr = 0x20000000000
    14  
    15  type Head struct {
    16  	Addr     unsafe.Pointer
    17  	MemSize  uintptr
    18  	TextSize uintptr
    19  	TextPtr  unsafe.Pointer
    20  }
    21  
    22  type Holder struct {
    23  	*Head
    24  	Data []byte
    25  }
    26  
    27  const exeName = "./child_exe"
    28  
    29  func main() {
    30  
    31  	fd, err := posix.MemfdCreate("test-mem", posix.MFD_ALLOW_SEALING)
    32  	CheckErr(err)
    33  
    34  	MemSize := posix.Getpagesize() * 4
    35  	err = posix.Ftruncate(fd, MemSize)
    36  	CheckErr(err)
    37  
    38  	buf, addr, err := posix.Mmap(unsafe.Pointer(ApproximatedAddress), MemSize, posix.PROT_WRITE, posix.MAP_SHARED, fd, 0)
    39  	CheckErr(err)
    40  
    41  	log.Printf("Got Address %p\n", unsafe.Pointer(addr))
    42  
    43  	text := "This works as Mmap in C"
    44  	offset := unsafe.Sizeof(Head{})
    45  
    46  	hdr := (*Head)(unsafe.Pointer(&buf[0]))
    47  	hdr.Addr = unsafe.Pointer(addr)
    48  	hdr.MemSize = uintptr(MemSize)
    49  	hdr.TextSize = uintptr(len(text))
    50  	hdr.TextPtr = unsafe.Pointer(&buf[offset])
    51  
    52  	holder := &Holder{
    53  		Head: hdr,
    54  		Data: unsafe.Slice(&buf[offset], uintptr(len(text))),
    55  	}
    56  
    57  	log.Println("bytes written:", copy(holder.Data, text))
    58  	log.Println("buf: ", buf[:offset+holder.TextSize])
    59  	log.Printf("%T = %+v", holder.Head, holder.Head)
    60  
    61  	/* Execute External Program which needs a pointer */
    62  	stdout, stderr := RunChild(exeName, uintptr(fd))
    63  	log.Printf("stderr: %s", stderr)
    64  	log.Printf("stdout: \n%s", stdout)
    65  
    66  	CheckErr(posix.Munmap(buf)) // unmap memory
    67  	CheckErr(posix.Close(fd))   // close anonymous file
    68  
    69  	log.Println("- example done -")
    70  }
    71  
    72  func RunChild(name string, fd uintptr) (out, err string) {
    73  	file := os.NewFile(fd, "anonymous-fd")
    74  	cmd := exec.Command(name)
    75  	cmd.ExtraFiles = []*os.File{file}
    76  	var stderr, stdout strings.Builder
    77  	cmd.Stderr = &stderr
    78  	cmd.Stdout = &stdout
    79  	if err := cmd.Run(); err != nil {
    80  		log.Fatal(err)
    81  	}
    82  	return stdout.String(), stderr.String()
    83  }
    84  
    85  func init() {
    86  	log.Println("compile C program")
    87  	compile := exec.Command("gcc", "-o", exeName, "_child.c")
    88  	compile.Env = append(os.Environ())
    89  	compile.Stderr = os.Stderr
    90  	compile.Stdout = os.Stdout
    91  	CheckErr(compile.Run())
    92  	log.Println("compile success")
    93  }
    94  
    95  func CheckErr(err error) {
    96  	if err != nil {
    97  		no := err.(syscall.Errno)
    98  		log.Fatalf("%s(%d): %v, msg: %s\nhelp: %s", posix.ErrnoName(no), no, err, posix.ErrnoString(no), posix.ErrnoHelp(no))
    99  	}
   100  }