github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/shm/shmi_linux.go (about)

     1  // +build linux,cgo
     2  
     3  package shm
     4  
     5  /*
     6  #cgo LDFLAGS: -lrt
     7  
     8  #include <sys/mman.h>
     9  #include <sys/types.h>
    10  #include <sys/stat.h>
    11  #include <fcntl.h>
    12  #include <stdio.h>
    13  #include <unistd.h>
    14  
    15  int _create(const char* name, int size, int flag) {
    16  	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
    17  
    18  	int fd = shm_open(name, flag, mode);
    19  	if (fd < 0) {
    20  		return -1;
    21  	}
    22  
    23  	if (ftruncate(fd, size) != 0) {
    24  		close(fd);
    25  		return -2;
    26  	}
    27  	return fd;
    28  }
    29  
    30  int Create(const char* name, int size) {
    31  	int flag = O_RDWR | O_CREAT;
    32  	return _create(name, size, flag);
    33  }
    34  
    35  int Open(const char* name, int size) {
    36  	int flag = O_RDWR;
    37  	return _create(name, size, flag);
    38  }
    39  
    40  void* Map(int fd, int size) {
    41  	void* p = mmap(
    42  		NULL, size,
    43  		PROT_READ | PROT_WRITE,
    44  		MAP_SHARED, fd, 0);
    45  	if (p == MAP_FAILED) {
    46  		return NULL;
    47  	}
    48  	return p;
    49  }
    50  
    51  void Close(int fd, void* p, int size) {
    52  	if (p != NULL) {
    53  		munmap(p, size);
    54  	}
    55  	if (fd != 0) {
    56  		close(fd);
    57  	}
    58  }
    59  
    60  void Delete(const char* name) {
    61  	shm_unlink(name);
    62  }
    63  */
    64  import "C"
    65  
    66  import (
    67  	"fmt"
    68  	"io"
    69  	"unsafe"
    70  )
    71  
    72  type sharedMemory struct {
    73  	name   string
    74  	fd     C.int
    75  	v      unsafe.Pointer
    76  	size   int32
    77  	parent bool
    78  }
    79  
    80  // create shared memory. return sharedMemory object.
    81  func create(name string, size int32) (*sharedMemory, error) {
    82  	name = "/" + name
    83  
    84  	fd := C.Create(C.CString(name), C.int(size))
    85  	if fd < 0 {
    86  		return nil, fmt.Errorf("create")
    87  	}
    88  
    89  	v := C.Map(fd, C.int(size))
    90  	if v == nil {
    91  		C.Close(fd, nil, C.int(size))
    92  		C.Delete(C.CString(name))
    93  	}
    94  
    95  	return &sharedMemory{name, fd, v, size, true}, nil
    96  }
    97  
    98  // open shared memory. return sharedMemory object.
    99  func open(name string, size int32) (*sharedMemory, error) {
   100  	name = "/" + name
   101  
   102  	fd := C.Open(C.CString(name), C.int(size))
   103  	if fd < 0 {
   104  		return nil, fmt.Errorf("open")
   105  	}
   106  
   107  	v := C.Map(fd, C.int(size))
   108  	if v == nil {
   109  		C.Close(fd, nil, C.int(size))
   110  		C.Delete(C.CString(name))
   111  	}
   112  
   113  	return &sharedMemory{name, fd, v, size, false}, nil
   114  }
   115  
   116  func (o *sharedMemory) close() error {
   117  	if o.v != nil {
   118  		C.Close(o.fd, o.v, C.int(o.size))
   119  		o.v = nil
   120  	}
   121  	if o.parent {
   122  		C.Delete(C.CString(o.name))
   123  	}
   124  	return nil
   125  }
   126  
   127  // read shared memory. return read size.
   128  func (o *sharedMemory) readAt(p []byte, off int64) (n int, err error) {
   129  	if off >= int64(o.size) {
   130  		return 0, io.EOF
   131  	}
   132  	if max := int64(o.size) - off; int64(len(p)) > max {
   133  		p = p[:max]
   134  	}
   135  	return f.BytesFromPtr(uintptr(o.v), p, off, o.size), nil
   136  }
   137  
   138  // write shared memory. return write size.
   139  func (o *sharedMemory) writeAt(p []byte, off int64) (n int, err error) {
   140  	if off >= int64(o.size) {
   141  		return 0, io.EOF
   142  	}
   143  	if max := int64(o.size) - off; int64(len(p)) > max {
   144  		p = p[:max]
   145  	}
   146  	return f.BytesToPtr(p, uintptr(o.v), off, o.size), nil
   147  }