zhangmeng
2019-08-26 3bd1f29975c0eaa6af8c99776b099faafbbfc250
提交 | 用户 | age
3bd1f2 1 // Copyright 2016 Tom Thorogood. All rights reserved.
Z 2 // Use of this source code is governed by a
3 // Modified BSD License license that can be found in
4 // the LICENSE file.
5
6 package shm
7
8 import (
9     "golang.org/x/sys/unix"
10     "sync/atomic"
11     "unsafe"
12
13     "github.com/tmthrgd/go-shm"
14 )
15
16 func OpenSimplex(name string) (*ReadWriteCloser, error) {
17     file, err := shm.Open(name, unix.O_RDWR, 0)
18     if err != nil {
19         return nil, err
20     }
21
22     defer file.Close()
23
24     data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED)
25     if err != nil {
26         return nil, err
27     }
28
29     shared := (*sharedMem)(unsafe.Pointer(&data[0]))
30
31     if atomic.LoadUint32((*uint32)(&shared.Version)) != version {
32         return nil, ErrInvalidSharedMemory
33     }
34
35     blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize)
36
37     if err = unix.Munmap(data); err != nil {
38         return nil, err
39     }
40
41     size := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount
42
43     data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
44     if err != nil {
45         return nil, err
46     }
47
48     shared = (*sharedMem)(unsafe.Pointer(&data[0]))
49     return &ReadWriteCloser{
50         name: name,
51
52         data:          data,
53         readShared:    shared,
54         writeShared:   shared,
55         size:          size,
56         fullBlockSize: blockHeaderSize + blockSize,
57
58         Flags: (*[len(shared.Flags)]uint32)(unsafe.Pointer(&shared.Flags[0])),
59     }, nil
60 }
61
62 func OpenDuplex(name string) (*ReadWriteCloser, error) {
63     file, err := shm.Open(name, unix.O_RDWR, 0)
64     if err != nil {
65         return nil, err
66     }
67
68     defer file.Close()
69
70     data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED)
71     if err != nil {
72         return nil, err
73     }
74
75     shared := (*sharedMem)(unsafe.Pointer(&data[0]))
76
77     if atomic.LoadUint32((*uint32)(&shared.Version)) != version {
78         return nil, ErrInvalidSharedMemory
79     }
80
81     blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize)
82
83     if err = unix.Munmap(data); err != nil {
84         return nil, err
85     }
86
87     sharedSize := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount
88     size := 2 * sharedSize
89
90     data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
91     if err != nil {
92         return nil, err
93     }
94
95     writeShared := (*sharedMem)(unsafe.Pointer(&data[0]))
96     return &ReadWriteCloser{
97         name: name,
98
99         data:          data,
100         readShared:    (*sharedMem)(unsafe.Pointer(&data[sharedSize])),
101         writeShared:   writeShared,
102         size:          size,
103         fullBlockSize: blockHeaderSize + blockSize,
104
105         Flags: (*[len(writeShared.Flags)]uint32)(unsafe.Pointer(&writeShared.Flags[0])),
106     }, nil
107 }