aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorroot <sina@snix.ir>2022-03-04 09:45:28 +0000
committerroot <sina@snix.ir>2022-03-04 09:45:28 +0000
commit7051e0896a5df51c00d09f1fa1936bc5ae7a6c9e (patch)
treef8ac703611469f9190de87a2d698288fcf9f2c8e /main.go
gosema ipc sysv linux
Diffstat (limited to 'main.go')
-rw-r--r--main.go143
1 files changed, 143 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..4300ae4
--- /dev/null
+++ b/main.go
@@ -0,0 +1,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
+
+}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR