golang操作共享内存
上代码
/*
#include <sys/shm.h>
#include <stdlib.h>
static int shmflag=IPC_CREAT|0640;
*/
import "C"
//打开共享内存通过文件特征id(不存在则创建共享内存,但是文件一定得在,得靠它的特征码),如果文件路径和gendid相同,那你打开的共享内存就是同一个
func CreateShare_Mem[T int | int32 | int64](pathname string, gendid int, dst_ptr **T) uintptr {
pn := C.CString(pathname)
key := C.ftok(pn, (C.int)(gendid))
C.free(unsafe.Pointer(pn))
var te T
shmid, _, err := syscall.Syscall(syscall.SYS_SHMGET, uintptr(key), unsafe.Sizeof(te), 01000|0640)
if err != 0 {
fmt.Println("[error]", err.Error())
return 0
}
var sharemem uintptr
sharemem, _, err = syscall.Syscall(syscall.SYS_SHMAT, shmid, 0, 0)
if err != 0 {
fmt.Println("[error]", err.Error())
return 0
}
*dst_ptr = (*T)(unsafe.Pointer(sharemem))
return shmid
}
//通过共享内存id来打开共享内存(前提是你的共享内存存在)
func GetShare_Mem[T int | int32 | int64](shmid int, dst_ptr **T) uintptr {
shm, _, err := syscall.Syscall(syscall.SYS_SHMAT, uintptr(shmid), 0, 0)
if len(err.Error()) < 1 {
*dst_ptr = (*T)(unsafe.Pointer(shm))
return 0
}
return shm
}
//关闭共享内存
func Close_Share_Mem(shm uintptr) error {
_, _, err := syscall.Syscall(syscall.SYS_SHMDT, shm, 0, 0)
if len(err.Error()) > 0 {
return fmt.Errorf(err.Error())
}
return nil
}
在系统中查看共享内存
ipcs -m #查看系统中现有的共享内存
ipcrm -m shmid #删除共享内存,shmid为共享内存id号
POSIX共享内存操作
posix 在mac和freebsd上跑shm_open可能会出问题,可以自行换为传统的open方法,shm_open父目录为/dev/shm。不同进程打开相同共享内存需要指定相同的文件,并且相同的size
/*
#include <stdio.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <fcntl.h>
void* open_shm(char* pathname,int sizes){
int shmid=shm_open(pathname,O_RDWR|O_CREAT,0640);
if (shmid>0){
if(ftruncate(shmid,sizes)!=-1){
void* ans=mmap(NULL,sizes,PROT_READ|PROT_WRITE,MAP_SHARED,shmid,0);
if(ans!=MAP_FAILED){
return ans;
}else{
fprintf(stderr,"mmap failed\n");
}
}else{
fprintf(stderr,"ftruncate failed\n");
}
}else{
fprintf(stderr,"open shmid failed\n");
}
return 0;
}
void unmap(void* src,int sizes){
msync(src,sizes,MS_SYNC);
munmap(src,sizes);
}
*/
func Shm_Open[T int | int32 | int64](pathname string, dst **T) unsafe.Pointer {
pathinfo := C.CString(pathname)
var te T
ansptr := C.open_shm(pathinfo, (C.int)(unsafe.Sizeof(te)))
if ansptr != nil {
*dst = (*T)(unsafe.Pointer(ansptr))
}
C.free(unsafe.Pointer(pathinfo))
return ansptr
}
// posix share memory close interface
func Shm_Close(ptr unsafe.Pointer, sizes int) {
C.unmap(ptr, (C.int)(sizes))
}
// posix share memory delete interface
func Shm_Del(shm_name string) {
shm_cname := C.CString(shm_name)
C.shm_unlink(shm_cname)
C.free(unsafe.Pointer(shm_cname))
}