chenshijun
2020-04-24 b4f186a5d496fd2085a2bf1405a6384cd7802236
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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))
}