From e43f714b49efafd1724b32edb1b09d57ce90f416 Mon Sep 17 00:00:00 2001
From: chenshijun <chenshijun@aiotlink.com>
Date: 星期四, 04 六月 2020 15:46:40 +0800
Subject: [PATCH] https://github.com/gen2brain/shm 修改arm和arm64的接口号
---
shm_linux_arm.go | 69 ++++
shm_dragonfly.go | 57 +++
shm_test.go | 38 ++
shm_linux_386.go | 65 ++++
.idea/.gitignore | 2
shm_netbsd.go | 57 +++
.idea/misc.xml | 6
README.md | 14
shm_darwin.go | 55 +++
shm_linux_amd64.go | 65 ++++
.idea/vcs.xml | 6
shm_freebsd.go | 51 +++
.idea/goshm.iml | 9
.idea/modules.xml | 8
shm_linux_arm64.go | 61 +++
shm.go | 136 ++++++++
shm_solaris.go | 198 ++++++++++++
shm_openbsd.go | 63 +++
18 files changed, 958 insertions(+), 2 deletions(-)
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..e7e9d11
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml
diff --git a/.idea/goshm.iml b/.idea/goshm.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/goshm.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="JavaScriptSettings">
+ <option name="languageLevel" value="ES6" />
+ </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..85c21cb
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/goshm.iml" filepath="$PROJECT_DIR$/.idea/goshm.iml" />
+ </modules>
+ </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Git" />
+ </component>
+</project>
\ No newline at end of file
diff --git a/README.md b/README.md
index a7689a6..83a1347 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,14 @@
-## goshm
+## go shm
+[](https://travis-ci.org/gen2brain/shm)
+[](https://godoc.org/github.com/gen2brain/shm)
+[](https://goreportcard.com/report/github.com/gen2brain/shm)
-go
+`shm` implements System V shared memory functions (`shmctl`, `shmget`, `shmat`, `shmdt`) in pure Go (except `solaris`, see [#24357](https://github.com/golang/go/issues/24357)).
+### Installation
+
+ go get -u github.com/gen2brain/shm
+
+### More
+
+For System V Message Queue IPC (i.e. `msgctl`, `msgget`, `msgrcv`, `msgsnd`) see [ipc](https://github.com/siadat/ipc).
diff --git a/shm.go b/shm.go
new file mode 100644
index 0000000..5541599
--- /dev/null
+++ b/shm.go
@@ -0,0 +1,136 @@
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+// Package shm implements System V shared memory functions (shmctl, shmget, shmat, shmdt).
+package shm
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// Constants.
+const (
+ // Mode bits for `shmget`.
+
+ // Create key if key does not exist.
+ IPC_CREAT = 01000
+ // Fail if key exists.
+ IPC_EXCL = 02000
+ // Return error on wait.
+ IPC_NOWAIT = 04000
+
+ // Special key values.
+
+ // Private key.
+ IPC_PRIVATE = 0
+
+ // Flags for `shmat`.
+
+ // Attach read-only access.
+ SHM_RDONLY = 010000
+ // Round attach address to SHMLBA.
+ SHM_RND = 020000
+ // Take-over region on attach.
+ SHM_REMAP = 040000
+ // Execution access.
+ SHM_EXEC = 0100000
+
+ // Commands for `shmctl`.
+
+ // Lock segment (root only).
+ SHM_LOCK = 1
+ // Unlock segment (root only).
+ SHM_UNLOCK = 12
+
+ // Control commands for `shmctl`.
+
+ // Remove identifier.
+ IPC_RMID = 0
+ // Set `ipc_perm` options.
+ IPC_SET = 1
+ // Get `ipc_perm' options.
+ IPC_STAT = 2
+)
+
+// Get allocates a shared memory segment.
+//
+// Get() returns the identifier of the shared memory segment associated with the value of the argument key.
+// A new shared memory segment is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE,
+// no shared memory segment corresponding to key exists, and IPC_CREAT is specified in shmFlg.
+//
+// If shmFlg specifies both IPC_CREAT and IPC_EXCL and a shared memory segment already exists for key,
+// then Get() fails with errno set to EEXIST.
+func Get(key int, size int, shmFlg int) (shmId int, err error) {
+ id, _, errno := syscall.Syscall(sysShmGet, uintptr(int32(key)), uintptr(int32(size)), uintptr(int32(shmFlg)))
+ if int(id) == -1 {
+ return -1, errno
+ }
+
+ return int(id), nil
+}
+
+// At attaches the shared memory segment identified by shmId.
+//
+// Using At() with shmAddr equal to NULL is the preferred, portable way of attaching a shared memory segment.
+func At(shmId int, shmAddr uintptr, shmFlg int) (data []byte, err error) {
+ addr, _, errno := syscall.Syscall(sysShmAt, uintptr(int32(shmId)), shmAddr, uintptr(int32(shmFlg)))
+ if int(addr) == -1 {
+ return nil, errno
+ }
+
+ length, err := Size(shmId)
+ if err != nil {
+ return nil, err
+ }
+
+ var b = struct {
+ addr uintptr
+ len int
+ cap int
+ }{addr, int(length), int(length)}
+
+ data = *(*[]byte)(unsafe.Pointer(&b))
+ return data, nil
+}
+
+// Dt detaches the shared memory segment.
+//
+// The to-be-detached segment must be currently attached with shmAddr equal to the value returned by the attaching At() call.
+func Dt(data []byte) error {
+ result, _, errno := syscall.Syscall(sysShmDt, uintptr(unsafe.Pointer(&data[0])), 0, 0)
+ if int(result) == -1 {
+ return errno
+ }
+
+ return nil
+}
+
+// Ctl performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmId.
+//
+// The buf argument is a pointer to a IdDs structure.
+func Ctl(shmId int, cmd int, buf *IdDs) (int, error) {
+ result, _, errno := syscall.Syscall(sysShmCtl, uintptr(int32(shmId)), uintptr(int32(cmd)), uintptr(unsafe.Pointer(buf)))
+ if int(result) == -1 {
+ return -1, errno
+ }
+
+ return int(result), nil
+}
+
+// Rm removes the shared memory segment.
+func Rm(shmId int) error {
+ _, err := Ctl(shmId, IPC_RMID, nil)
+ return err
+}
+
+// Size returns size of shared memory segment.
+func Size(shmId int) (int64, error) {
+ var idDs IdDs
+
+ _, err := Ctl(shmId, IPC_STAT, &idDs)
+ if err != nil {
+ return 0, err
+ }
+
+ return int64(idDs.SegSz), nil
+}
diff --git a/shm_darwin.go b/shm_darwin.go
new file mode 100644
index 0000000..c1962dd
--- /dev/null
+++ b/shm_darwin.go
@@ -0,0 +1,55 @@
+package shm
+
+import (
+ "syscall"
+)
+
+// System call constants.
+const (
+ sysShmAt = syscall.SYS_SHMAT
+ sysShmCtl = syscall.SYS_SHMCTL
+ sysShmDt = syscall.SYS_SHMDT
+ sysShmGet = syscall.SYS_SHMGET
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint16
+ // Sequence number.
+ Seq uint16
+ // Key.
+ Key int32
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Number of current attaches.
+ Nattch uint16
+ // Padding.
+ PadCgo0 [2]byte
+ // Padding.
+ PadCgo1 [8]byte
+ // Padding.
+ PadCgo2 [8]byte
+ // Padding.
+ PadCgo3 [8]byte
+ // Padding.
+ PadCgo4 [8]byte
+}
diff --git a/shm_dragonfly.go b/shm_dragonfly.go
new file mode 100644
index 0000000..9727a92
--- /dev/null
+++ b/shm_dragonfly.go
@@ -0,0 +1,57 @@
+package shm
+
+import (
+ "syscall"
+)
+
+// System call constants.
+const (
+ sysShmAt = syscall.SYS_SHMAT
+ sysShmCtl = syscall.SYS_SHMCTL
+ sysShmDt = syscall.SYS_SHMDT
+ sysShmGet = syscall.SYS_SHMGET
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Creator's user ID.
+ Cuid uint16
+ // Creator's group ID.
+ Cgid uint16
+ // Owner's user ID.
+ Uid uint16
+ // Owner's group ID.
+ Gid uint16
+ // Read/write permission.
+ Mode uint16
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ PadCgo0 [4]byte
+ // Key.
+ Key int64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Number of current attaches.
+ Nattch uint32
+ // Padding.
+ PadCgo0 [4]byte
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+ // Internal.
+ Internal *byte
+}
diff --git a/shm_freebsd.go b/shm_freebsd.go
new file mode 100644
index 0000000..af6cc89
--- /dev/null
+++ b/shm_freebsd.go
@@ -0,0 +1,51 @@
+package shm
+
+// System call constants.
+const (
+ sysShmAt = 228
+ sysShmCtl = 229
+ sysShmDt = 230
+ sysShmGet = 231
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Read/write permission.
+ Mode uint16
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ PadCgo0 [4]byte
+ // Key.
+ Key int64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Number of current attaches.
+ Nattch int32
+ // Padding.
+ PadCgo0 [4]byte
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+}
diff --git a/shm_linux_386.go b/shm_linux_386.go
new file mode 100644
index 0000000..3fa70ba
--- /dev/null
+++ b/shm_linux_386.go
@@ -0,0 +1,65 @@
+package shm
+
+// System call constants.
+const (
+ sysShmAt = 30
+ sysShmCtl = 31
+ sysShmDt = 67
+ sysShmGet = 29
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Key.
+ Key int32
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint16
+ // Padding.
+ Pad1 uint16
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ Pad2 uint16
+ // Reserved.
+ GlibcReserved1 uint32
+ // Reserved.
+ GlibcReserved2 uint32
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint32
+ // Last attach time.
+ Atime int32
+ // Reserved.
+ GlibcReserved1 uint32
+ // Last detach time.
+ Dtime int32
+ // Reserved.
+ GlibcReserved2 uint32
+ // Last change time.
+ Ctime int32
+ // Reserved.
+ GlibcReserved3 uint32
+ // Pid of creator.
+ Cpid int32
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Number of current attaches.
+ Nattch uint32
+ // Reserved.
+ GlibcReserved4 uint32
+ // Reserved.
+ GlibcReserved5 uint32
+}
diff --git a/shm_linux_amd64.go b/shm_linux_amd64.go
new file mode 100644
index 0000000..8a5ff4f
--- /dev/null
+++ b/shm_linux_amd64.go
@@ -0,0 +1,65 @@
+package shm
+
+import (
+ "syscall"
+)
+
+// System call constants.
+const (
+ sysShmAt = syscall.SYS_SHMAT
+ sysShmCtl = syscall.SYS_SHMCTL
+ sysShmDt = syscall.SYS_SHMDT
+ sysShmGet = syscall.SYS_SHMGET
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Key.
+ Key int32
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint16
+ // Padding.
+ Pad1 uint16
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ Pad2 uint16
+ // Padding.
+ PadCgo0 [4]byte
+ // Reserved.
+ GlibcReserved1 uint64
+ // Reserved.
+ GlibcReserved2 uint64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+ // Pid of creator.
+ Cpid int32
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Number of current attaches.
+ Nattch uint64
+ // Reserved.
+ GlibcReserved4 uint64
+ // Reserved.
+ GlibcReserved5 uint64
+}
diff --git a/shm_linux_arm.go b/shm_linux_arm.go
new file mode 100644
index 0000000..78011ec
--- /dev/null
+++ b/shm_linux_arm.go
@@ -0,0 +1,69 @@
+package shm
+
+// System call constants.
+const (
+ //sysShmAt = 21
+ //sysShmCtl = 24
+ //sysShmDt = 22
+ //sysShmGet = 23
+ sysShmAt = 305
+ sysShmDt = 306
+ sysShmGet = 307
+ sysShmCtl = 308
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Key.
+ Key int32
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint16
+ // Padding.
+ Pad1 uint16
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ Pad2 uint16
+ // Reserved.
+ GlibcReserved1 uint32
+ // Reserved.
+ GlibcReserved2 uint32
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint32
+ // Last attach time.
+ Atime int32
+ // Reserved.
+ GlibcReserved1 uint32
+ // Last detach time.
+ Dtime int32
+ // Reserved.
+ GlibcReserved2 uint32
+ // Last change time.
+ Ctime int32
+ // Reserved.
+ GlibcReserved3 uint32
+ // Pid of creator.
+ Cpid int32
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Number of current attaches.
+ Nattch uint32
+ // Reserved.
+ GlibcReserved4 uint32
+ // Reserved.
+ GlibcReserved5 uint32
+}
diff --git a/shm_linux_arm64.go b/shm_linux_arm64.go
new file mode 100644
index 0000000..3550210
--- /dev/null
+++ b/shm_linux_arm64.go
@@ -0,0 +1,61 @@
+package shm
+
+// System call constants.
+const (
+ //sysShmAt = 21
+ //sysShmCtl = 24
+ //sysShmDt = 22
+ //sysShmGet = 23
+ sysShmGet = 194
+ sysShmCtl = 195
+ sysShmAt = 196
+ sysShmDt = 197
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Key.
+ Key int32
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint32
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ Pad1 uint16
+ // Reserved.
+ GlibcReserved1 uint64
+ // Reserved.
+ GlibcReserved2 uint64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+ // Pid of creator.
+ Cpid int32
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Number of current attaches.
+ Nattch uint64
+ // Reserved.
+ GlibcReserved5 uint64
+ // Reserved.
+ GlibcReserved6 uint64
+}
diff --git a/shm_netbsd.go b/shm_netbsd.go
new file mode 100644
index 0000000..65ed5ba
--- /dev/null
+++ b/shm_netbsd.go
@@ -0,0 +1,57 @@
+package shm
+
+import (
+ "syscall"
+)
+
+// System call constants.
+const (
+ sysShmAt = syscall.SYS_SHMAT
+ sysShmCtl = syscall.SYS_SHMCTL
+ sysShmDt = syscall.SYS_SHMDT
+ sysShmGet = syscall.SYS_SHMGET
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint32
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ PadCgo0 [2]byte
+ // Key.
+ Key int64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz uint64
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Number of current attaches.
+ Nattch uint32
+ // Padding.
+ PadCgo0 [4]byte
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+ // SysV stupidity
+ XShmInternal *byte
+}
diff --git a/shm_openbsd.go b/shm_openbsd.go
new file mode 100644
index 0000000..9f8e19a
--- /dev/null
+++ b/shm_openbsd.go
@@ -0,0 +1,63 @@
+package shm
+
+import (
+ "syscall"
+)
+
+// System call constants.
+const (
+ sysShmAt = syscall.SYS_SHMAT
+ sysShmCtl = syscall.SYS_SHMCTL
+ sysShmDt = syscall.SYS_SHMDT
+ sysShmGet = syscall.SYS_SHMGET
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Owner's user ID.
+ Cuid uint32
+ // Owner's group ID.
+ Cgid uint32
+ // Creator's user ID.
+ Uid uint32
+ // Creator's group ID.
+ Gid uint32
+ // Read/write permission.
+ Mode uint32
+ // Sequence number.
+ Seq uint16
+ // Padding.
+ PadCgo0 [2]byte
+ // Key.
+ Key int64
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Size of segment in bytes.
+ SegSz int32
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Number of current attaches.
+ Nattch int16
+ // Padding.
+ PadCgo0 [2]byte
+ // Last attach time.
+ Atime int64
+ // Internal.
+ XShmAtimensec int64
+ // Last detach time.
+ Dtime int64
+ // Internal.
+ XShmDtimensec int64
+ // Last change time.
+ Ctime int64
+ // Internal.
+ XShmCtimensec int64
+ // Internal.
+ XShmInternal *byte
+}
diff --git a/shm_solaris.go b/shm_solaris.go
new file mode 100644
index 0000000..87eab2d
--- /dev/null
+++ b/shm_solaris.go
@@ -0,0 +1,198 @@
+// +build solaris
+
+package shm
+
+// #include <sys/ipc.h>
+// #include <sys/shm.h>
+// #include <errno.h>
+import "C"
+
+import (
+ "unsafe"
+)
+
+// Perm is used to pass permission information to IPC operations.
+type Perm struct {
+ // Owner's user ID.
+ Uid uint32
+ // Owner's group ID.
+ Gid uint32
+ // Creator's user ID.
+ Cuid uint32
+ // Creator's group ID.
+ Cgid uint32
+ // Read/write permission.
+ Mode uint32
+ // Sequence number.
+ Seq uint32
+ // Key.
+ Key int32
+}
+
+// IdDs describes shared memory segment.
+type IdDs struct {
+ // Operation permission struct.
+ Perm Perm
+ // Padding.
+ PadCgo0 [4]byte
+ // Size of segment in bytes.
+ SegSz uint64
+ // Flags.
+ Flags uint64
+ // Internal.
+ Lkcnt uint16
+ // Padding.
+ PadCgo1 [2]byte
+ // Pid of last shmat/shmdt.
+ Lpid int32
+ // Pid of creator.
+ Cpid int32
+ // Padding.
+ PadCgo2 [4]byte
+ // Number of current attaches.
+ Nattch uint64
+ // Internal.
+ Cnattch uint64
+ // Last attach time.
+ Atime int64
+ // Last detach time.
+ Dtime int64
+ // Last change time.
+ Ctime int64
+ // Internal.
+ Amp *byte
+ // Internal.
+ Gransize uint64
+ // Internal.
+ Allocated uint64
+ // Padding.
+ Pad4 [1]int64
+}
+
+// Constants.
+const (
+ // Mode bits for `shmget`.
+
+ // Create key if key does not exist.
+ IPC_CREAT = 01000
+ // Fail if key exists.
+ IPC_EXCL = 02000
+ // Return error on wait.
+ IPC_NOWAIT = 04000
+
+ // Special key values.
+
+ // Private key.
+ IPC_PRIVATE = 0
+
+ // Flags for `shmat`.
+
+ // Attach read-only access.
+ SHM_RDONLY = 010000
+ // Round attach address to SHMLBA.
+ SHM_RND = 020000
+ // Take-over region on attach.
+ SHM_REMAP = 040000
+ // Execution access.
+ SHM_EXEC = 0100000
+
+ // Commands for `shmctl`.
+
+ // Lock segment (root only).
+ SHM_LOCK = 1
+ // Unlock segment (root only).
+ SHM_UNLOCK = 12
+
+ // Control commands for `shmctl`.
+
+ // Remove identifier.
+ IPC_RMID = 10
+ // Set `ipc_perm` options.
+ IPC_SET = 11
+ // Get `ipc_perm' options.
+ IPC_STAT = 12
+)
+
+// Get allocates a shared memory segment.
+//
+// Get() returns the identifier of the shared memory segment associated with the value of the argument key.
+// A new shared memory segment is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE,
+// no shared memory segment corresponding to key exists, and IPC_CREAT is specified in shmFlg.
+//
+// If shmFlg specifies both IPC_CREAT and IPC_EXCL and a shared memory segment already exists for key,
+// then Get() fails with errno set to EEXIST.
+func Get(key int, size int, shmFlg int) (shmId int, err error) {
+ id, errno := C.shmget(C.key_t(key), C.size_t(size), C.int(shmFlg))
+
+ if int(id) == -1 {
+ return -1, errno
+ }
+
+ return int(id), nil
+}
+
+// At attaches the shared memory segment identified by shmId.
+//
+// Using At() with shmAddr equal to NULL is the preferred, portable way of attaching a shared memory segment.
+func At(shmId int, shmAddr uintptr, shmFlg int) (data []byte, err error) {
+ addr, errno := C.shmat(C.int(shmId), unsafe.Pointer(shmAddr), C.int(shmFlg))
+ if int(uintptr(addr)) == -1 {
+ return nil, errno
+ }
+
+ length, err := Size(shmId)
+ if err != nil {
+ return nil, err
+ }
+
+ var b = struct {
+ addr uintptr
+ len int
+ cap int
+ }{uintptr(addr), int(length), int(length)}
+
+ data = *(*[]byte)(unsafe.Pointer(&b))
+ return data, nil
+}
+
+// Dt detaches the shared memory segment.
+//
+// The to-be-detached segment must be currently attached with shmAddr equal to the value returned by the attaching At() call.
+func Dt(data []byte) error {
+ result, errno := C.shmdt(unsafe.Pointer(&data[0]))
+ if int(result) == -1 {
+ return errno
+ }
+
+ return nil
+}
+
+// Ctl performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmId.
+//
+// The buf argument is a pointer to a IdDs structure.
+func Ctl(shmId int, cmd int, buf *IdDs) (int, error) {
+ result, errno := C.shmctl(C.int(shmId), C.int(cmd), (*C.struct_shmid_ds)(unsafe.Pointer(buf)))
+ if int(result) == -1 {
+ return -1, errno
+ }
+
+ return int(result), nil
+}
+
+// Rm removes the shared memory segment.
+func Rm(shmId int) error {
+ _, err := Ctl(shmId, IPC_RMID, nil)
+ return err
+}
+
+// Size returns size of shared memory segment.
+func Size(shmId int) (int64, error) {
+ var idDs IdDs
+
+ _, err := Ctl(shmId, IPC_STAT, &idDs)
+ if err != nil {
+ return 0, err
+ }
+
+ return int64(idDs.SegSz), nil
+}
diff --git a/shm_test.go b/shm_test.go
new file mode 100644
index 0000000..faa9a22
--- /dev/null
+++ b/shm_test.go
@@ -0,0 +1,38 @@
+package shm
+
+import (
+ "testing"
+)
+
+func TestShm(t *testing.T) {
+ shmSize := 65536
+
+ shmId, err := Get(IPC_PRIVATE, shmSize, IPC_CREAT|0777)
+ if err != nil {
+ t.Errorf("Get: %v", err)
+ }
+
+ data, err := At(shmId, 0, 0)
+ if err != nil {
+ t.Errorf("At: %v", err)
+ }
+
+ size, err := Size(shmId)
+ if err != nil {
+ t.Errorf("Size: %v", err)
+ }
+
+ if int(size) != shmSize {
+ t.Errorf("Wrong size got %d expected %d", size, shmSize)
+ }
+
+ err = Rm(shmId)
+ if err != nil {
+ t.Errorf("Rm: %v", err)
+ }
+
+ err = Dt(data)
+ if err != nil {
+ t.Errorf("Dt: %v", err)
+ }
+}
--
Gitblit v1.8.0