golang 结合cgo 操作共享内存,包括虚拟内存mmap版和内存shm版

如下是源代码实现直接编译即可使用:

//author sam by 20170621
// 使用示例:
// package utils

// import (
//  "fmt"
//  u "lpaiche.com/utils"
//  "testing"
// )

// type MyData struct {
//  Col1 int
//  Col2 int
//  Col3 int
//  Col4 int
// }

// //-----------------------------------------test_mmap_shm----------------------------
// func TestWriteMmapShm(t *testing.T) {
//  shm := u.NewShmMmap("test")
//  fmt.Println(shm)
//  fmt.Println("写入共享内存")
//  data := (*MyData)(shm.GetWritePointer())

//  data.Col1 = 105
//  data.Col2 = 276
//  data.Col3 = 2021
//  data.Col4 = 2020

//  fmt.Println(data)
// }

// func TestReadMmapShm(t *testing.T) {
//  fmt.Println("读取共享内存")
//  shm := u.NewShmMmap("test")
//  data1 := (*MyData)(shm.GetReadPointer())
//  fmt.Println(data1)
// }

// func TestFreeMmapShm(t *testing.T) {
//  fmt.Println("删除共享内存")
//  shm := u.NewShmMmap("test")
//  shm.Remove()
// }

// //-------------------------------------------test_mem_shm------------------------
// func TestShmmemGetWritePointer(t *testing.T) {
//  shm := u.NewShmMem("/tmp/shm")
//  fmt.Println(shm)

//  data := (*MyData)(shm.GetWritePointer())
//  defer shm.Close()

//  data.Col1 = 1111
//  data.Col2 = 2222
//  data.Col3 = 3333
//  data.Col4 = 4444

//  fmt.Println(data)

// }

// func TestShmmemGetReadPointer(t *testing.T) {
//  fmt.Println("读取共享内存")
//  shm := u.NewShmMem("/tmp/shm")
//  data1 := (*MyData)(shm.GetReadPointer())
//  fmt.Println(data1)
// }

// func TestShmmemRemove(t *testing.T) {
//  shm := u.NewShmMem("/tmp/shm")
//  fmt.Println("删除共享内存")
//  shm.Remove()
// }

package utils

/*
#cgo linux LDFLAGS: -lrt

#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>

//-----------------cgo_mmap----------------------------
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int my_shm_new(char *name) {
    //shm_unlink(name);
    return shm_open(name, O_RDWR|O_CREAT|O_EXCL, FILE_MODE);
}

int my_shm_open(char *name) {
    return shm_open(name, O_RDWR, FILE_MODE);
}

void my_shm_free(char *name){
    shm_unlink(name);
}

//------------------cgo_shm-------------------------
int my_shmmem_open(char *file,int size,int open_flag){
    int shm_id;
    key_t key;
    key = ftok(file, 0x111);
    if(key == -1){
        return -1;
    }
    if(open_flag)
        shm_id = shmget(key, size, IPC_CREAT|IPC_EXCL|0600);
    else
        shm_id = shmget(key, 0, 0);
    if(shm_id == -1){
        return -1;
    }
    return shm_id;
}

int my_shmmem_rm(int shm_id){
    shmctl(shm_id, IPC_RMID, NULL);
    return 0;
}

*/
import "C"

import (
    "fmt"
    "unsafe"
)

//------------------------------mmap实现共享内存操作-------------------------------------------------------------
type ShmMmap struct {
    name string
    size int
}

func NewShmMmap(shm_name string, shm_size ...int) *ShmMmap {
    shm_size1 := 1 * 1000 * 1000 * 1000 //默认共享内存大小1G
    if shm_size != nil {
        shm_size1 = shm_size[0]
    }

    shmm := ShmMmap{name: shm_name, size: shm_size1}
    return &shmm
}

func (this *ShmMmap) GetWritePointer() unsafe.Pointer {

    this.Remove()

    fd, err := C.my_shm_new(C.CString(this.name))
    if err != nil {
        fmt.Println(err)
        return nil
    }

    shm_size := (C.__off_t)(this.size)
    C.ftruncate(fd, shm_size)

    ptr, err := C.mmap(nil, 4*1000*1000*1000, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)
    if err != nil {
        fmt.Println(err)
        return nil
    }
    C.close(fd)

    return (unsafe.Pointer(ptr))
}

func (this *ShmMmap) Remove() {
    C.my_shm_free(C.CString(this.name))
}

func (this *ShmMmap) GetReadPointer() unsafe.Pointer {
    fd, err := C.my_shm_open(C.CString(this.name))
    if err != nil {
        fmt.Println(err)
        return nil
    }
    shm_size := (C.size_t)(this.size)
    ptr, err := C.mmap(nil, shm_size, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)
    if err != nil {
        fmt.Println(err)
        return nil
    }
    C.close(fd)

    return (unsafe.Pointer(ptr))
}

//---------------------------------------shm实现共享内存操作------------------------------------------

type ShmMem struct {
    filename string
    size     int
    shmid    int
    pointer  unsafe.Pointer
}

func NewShmMem(pathfilename string, shm_size ...int) *ShmMem {
    shm_size1 := 4096 //默认共享内存大小4k
    if shm_size != nil {
        shm_size1 = shm_size[0]
    }
    shmm := ShmMem{filename: pathfilename, size: shm_size1, shmid: 0}
    return &shmm
}

func (this *ShmMem) initShmit() {
    filename := C.CString(this.filename)
    defer C.free(unsafe.Pointer(filename))
    this.shmid = int(C.my_shmmem_open(filename, C.int(this.size), C.int(1)))
    if this.shmid < 0 {
        this.shmid = int(C.my_shmmem_open(filename, C.int(this.size), C.int(0)))
    }
    if this.shmid < 0 {
        fmt.Println("open share memery failed!")
        Panic("open share memery failed! ")
    }
}

func (this *ShmMem) GetWritePointer() unsafe.Pointer {
    this.initShmit()
    addr := C.shmat(C.int(this.shmid), nil, 0)
    this.pointer = unsafe.Pointer(addr)

    return this.pointer

}
func (this *ShmMem) GetReadPointer() unsafe.Pointer {
    return this.GetWritePointer()
}

func (this *ShmMem) Close() {
    C.shmdt(this.pointer)
}

func (this *ShmMem) Remove() {
    this.initShmit()
    C.my_shmmem_rm(C.int(this.shmid))
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值