github.com/Ptt-official-app/go-bbs@v0.12.0/cache/systemvshm.go (about) 1 package cache 2 3 import ( 4 "fmt" 5 "reflect" 6 "runtime" 7 "unsafe" 8 ) 9 10 // shmget: get shared memort area identifier, please see man 2 shmget 11 func Shmget(key int, size int, flag int) (int, error) { 12 return shmget(key, size, flag) 13 } 14 15 // shmat: map/unmap shared memory, plase see man 2 shmat. 16 // golang gc won't affect on this. 17 func Shmat(shmid int, shmaddr uintptr, shmflg int) (uintptr, error) { 18 return shmat(shmid, shmaddr, shmflg) 19 } 20 21 // shmdt: map/unmap shared memory, plase see man 2 shmdt. 22 func Shmdt(shmaddr uintptr) (int, error) { 23 return shmdt(shmaddr) 24 } 25 26 // shmctl: shared memory control operations 27 func Shmctl(shmid int, cmd int, buf *ShmidDs) (int, error) { 28 return shmctl(shmid, cmd, buf) 29 } 30 31 const ( 32 IPCCreate = 00001000 33 34 IPCRMID = 0 35 IPCSet = 1 36 IPCStat = 2 37 ) 38 39 type SHM struct { 40 buf []byte 41 } 42 43 func CreateKey(key int, size int) (*SHM, error) { 44 flag := 0 45 if size != 0 { 46 // create 47 flag = IPCCreate | 0600 48 } 49 50 shmID, err := Shmget(key, size, flag) 51 if err != nil { 52 return nil, fmt.Errorf("shmget error: %w", err) 53 } 54 // fmt.Println("shmid", shmID) 55 // size = 4 56 if size == 0 { 57 58 ds := ShmidDs{} 59 _, err = Shmctl(shmID, IPCStat, &ds) 60 if err != nil { 61 return nil, fmt.Errorf("shmctl error: %w", err) 62 } 63 // fmt.Printf("%+v\n", ds) 64 size = int(ds.ShmSegsz) 65 } 66 67 // v := 0 68 69 ptr, err := Shmat(shmID, uintptr(0), 0) 70 if err != nil { 71 return nil, fmt.Errorf("shmat error: %w", err) 72 } 73 // fmt.Println("ptr", *(*int)(ptr)) 74 // fmt.Println("size", size) 75 b := []byte{} 76 hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 77 hdr.Cap = size 78 hdr.Len = size 79 hdr.Data = ptr 80 81 ret := SHM{ 82 buf: b, 83 } 84 85 // For GC 86 runtime.SetFinalizer(&ret, (*SHM).Close) 87 return &ret, nil 88 } 89 90 // OpenKey open a shm which is already exists. 91 func OpenKey(key int) (*SHM, error) { 92 return CreateKey(key, 0) 93 } 94 func RemoveKey(key int) error { 95 shmID, err := Shmget(key, 0, 0) 96 if err != nil { 97 return fmt.Errorf("shmget error: %w", err) 98 } 99 100 // ds := ShmidDs{} 101 _, err = Shmctl(shmID, IPCRMID, nil) 102 if err != nil { 103 return fmt.Errorf("shmctl error: %w", err) 104 } 105 return nil 106 } 107 108 func (s *SHM) Bytes() []byte { 109 return s.buf 110 } 111 112 func (s *SHM) Close() error { 113 hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s.buf)) 114 ptr := hdr.Data 115 _, err := Shmdt(ptr) 116 117 // release GC setting 118 runtime.SetFinalizer(s, nil) 119 if err != nil { 120 return fmt.Errorf("shmdt error: %w", err) 121 } 122 return nil 123 } 124 125 // func shmNew(key int, size int) int { 126 127 // shmid, err := Shmget(key, size, 0) 128 129 // shmptr := C.shmat(C.int(shmid), unsafe.Pointer(nil), 0) 130 // fmt.Printf("nowValue = %d, pos = %v %v\n", *(*int)(shmptr), (*int)(shmptr), shmptr) 131 132 // return int(shmid) 133 134 // } 135 136 // void * shm_new(const int key, const int size) { 137 // shmid = shmget(key, size, 0); 138 // printf("shmid: %d %s \n", shmid, strerror(errno)); 139 // if(shmid == -1){ 140 // // Create 141 // shmid = shmget(key, size, IPC_CREAT | 0600); 142 // if(shmid == -1){ 143 // printf("shmid: %d %s \n", shmid, strerror(errno)); 144 // exit(-1); 145 // } 146 // } 147 148 // void * shmptr = (void *) shmat(shmid, NULL, 0); 149 // if((int)shmptr == -1){ 150 // printf("shmat: %p %s \n", shmptr, strerror(errno)); 151 // exit(-2); 152 // } 153 // printf("nowValue = %d, pos: %p\n", *(int*)shmptr, shmptr); 154 // *(int*)shmptr = *(int*)shmptr + 1; 155 // return shmptr; 156 // } 157 158 // func main() { 159 // shmNew(3, 4) 160 // fmt.Println("OK") 161 // }