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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"gosema/sysv"
"os"
"time"
"golang.org/x/sys/unix"
)
/*
an example of ipc sysv with golang - this can be done with newer apis
like shm_open(), /dev/shm or mmap() too, sysv is the oldest way to do
this, and it's commonly used.
author: sina@snix.ir
*/
const (
//SHMSEMFLG = 0666 | unix.IPC_CREAT | unix.IPC_EXCL
SHMSEMFLG = 0666 | unix.IPC_CREAT // open shm and sem with this flag
SEMSHEMID = 0x12 // shm and sem id
NUMSOFSEM = 0x01 // number of sems
SHRDMEMRY = 0x20 // size of shared memory (32 byte)
)
const SEM_A = 0x00
func clntOrServ() bool {
if os.Args[1] == server {
return true
}
if os.Args[1] != client {
usage(os.Args[0])
}
return false
}
func main() {
defer defexit()
if len(os.Args) < 2 {
usage(os.Args[0])
}
serv := clntOrServ()
semkey, err := sysv.Ftok(os.DevNull, SEMSHEMID)
if err != nil {
fatal(err)
}
shmkey, err := sysv.Ftok(os.DevNull, SEMSHEMID)
if err != nil {
fatal(err)
}
shmidd, err := unix.SysvShmGet(int(shmkey), SHRDMEMRY, SHMSEMFLG)
if err != nil {
fatal(err)
}
defer unix.SysvShmCtl(shmidd, unix.IPC_RMID, &unix.SysvShmDesc{})
mem, err := unix.SysvShmAttach(shmidd, 0, 0)
if err != nil {
fatal(err)
}
defer unix.SysvShmDetach(mem)
if len(mem) != SHRDMEMRY {
fatal(errNotSame)
}
logst("shared memory is now ready to use", SHRDMEMRY)
sempht, err := sysv.NewSemGet(int(semkey), NUMSOFSEM, SHMSEMFLG)
if err != nil {
fatal(err)
}
defer sempht.DelSem()
// set semval to 1, which force client to wait for semaphore
switch {
case serv:
if err := sempht.SetVal(SEM_A, 1); err != nil {
warng(err)
}
for {
l, _ := sempht.GetVal(SEM_A) // value of semaphore
s, _ := sempht.GetPID(SEM_A) // pid that holds semaphore
fmt.Printf("sem locked by process pid: %d, semval: %d\n", s, l)
// lock sem[0], make semval = semval-1 and if semval is 0 then no one
// can lock semaphore any more
if err := sempht.Lock(SEM_A); err != nil {
warng(err)
continue
}
// l, _ = sempht.GetVal(SEM_A)
// fmt.Println(l)
// write some dummy random data to shared mem
if err := makeRand(mem); err != nil {
warng(err)
}
time.Sleep(time.Second) // every one sec
fmt.Println("i just put some random jokes in memory.. yeay")
if err := sempht.Unlock(SEM_A); err != nil {
warng(err)
} //unlock sem[0], make semval = semval+1
}
}
for {
if err := sempht.Lock(SEM_A); err != nil {
warng(err)
continue // do not unlock it if you haven't locked it
}
fmt.Printf("data: %s\n", hex.EncodeToString(mem))
if err := sempht.Unlock(SEM_A); err != nil {
warng(err)
}
}
}
func makeRand(b []byte) error {
_, err := rand.Read(b)
return err
}
|