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
+[![TravisCI Build Status](https://travis-ci.org/gen2brain/shm.svg?branch=master)](https://travis-ci.org/gen2brain/shm) 
+[![GoDoc](https://godoc.org/github.com/gen2brain/shm?status.svg)](https://godoc.org/github.com/gen2brain/shm) 
+[![Go Report Card](https://goreportcard.com/badge/github.com/gen2brain/shm?branch=master)](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