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