package shmqueue import ( "reflect" "unsafe" ) // []byte struct type ShmDataInfo struct { Len uint32 Cache []byte } // shmData2Info convert []byte to *ShmDataInfo func shmData2Info(b []byte) *ShmDataInfo { return (*ShmDataInfo)(unsafe.Pointer( (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data, )) } const SHMSLICEOFFSET int = 32 // ConvertToSlice convert to []byte func ptr2Slice(s unsafe.Pointer, size,cap int) []byte { var x reflect.SliceHeader x.Len = size x.Cap = cap x.Data = uintptr(s) return *(*[]byte)(unsafe.Pointer(&x)) } //WriteShmData data待写入的数据; shmId:共享内存id,只attach,不create // 把data写入shmId对应的shm中, 流程: attach->写入数据->detach // 适合shm是空的,解码使用 func WriteShmData(data []byte, shmId int) error { shmData, err := Attach(shmId) if err != nil { return err } sdi := shmData2Info(shmData) if len(data) <= len(shmData)-SHMSLICEOFFSET { sdi.Len = uint32(len(data)) } else { sdi.Len = uint32(len(shmData)-SHMSLICEOFFSET) } tmpData := ptr2Slice(unsafe.Pointer(&sdi.Cache), int(sdi.Len), len(shmData)-SHMSLICEOFFSET) copy(tmpData, data) err = Detach(shmData) if err != nil { return err } return nil } //ReadShmData attach到shmId对应的共享内存,并读出数据[]byte // 使用之后需要detach func ReadShmData(shmId int) ([]byte, error) { shmData, err := Attach(shmId) if err != nil { return nil, err } sdi := shmData2Info(shmData) tmpData := ptr2Slice(unsafe.Pointer(&sdi.Cache), int(sdi.Len), len(shmData)-SHMSLICEOFFSET) return tmpData, nil } //DeepCopyDataToShm 深拷贝,把内存的数据拷贝attach之后共享内存中 // 输入: shmData是attach返回的[]byte, memdData是内存中的数据 // 写入数据到共享内存使用:attach->DeepCopyDataToShm->detach // 适合解码使用 func DeepCopyDataToShm(memData,shmData []byte) { sdi := shmData2Info(shmData) if len(memData) <= len(shmData)-SHMSLICEOFFSET { sdi.Len = uint32(len(memData)) } else { sdi.Len = uint32(len(shmData)-SHMSLICEOFFSET) } tmpData := ptr2Slice(unsafe.Pointer(&sdi.Cache), int(sdi.Len), len(shmData)-SHMSLICEOFFSET) copy(tmpData, memData) } //ReadShmData 把attach后的shmData转成内存data // 输入:attach到共享内存得到的shmData // 输出:转换后的data // 从共享内存中读取数据使用:attach->ConvertShmToData->只读,业务处理结束后->detach func ConvertShmToData(shmData []byte) []byte { sdi := shmData2Info(shmData) tmpData := ptr2Slice(unsafe.Pointer(&sdi.Cache), int(sdi.Len), len(shmData)-SHMSLICEOFFSET) return tmpData } //UpdateDataToShm (类似浅拷贝)更新数据到共享内存 // 输入: ConvertShmToData得到的数据data,经过业务处理后,该数据有变化,需要update到shm里 // 更新数据到共享内存使用: attach->ConvertShmToData->修改data数据,业务处理结束后->UpdateDataToShm->detach func UpdateDataToShm(data, shmData []byte) { sdi := shmData2Info(shmData) sdi.Len = uint32(len(data)) }