前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang直接操作共享内存

golang直接操作共享内存

作者头像
码农二狗
发布2020-01-03 11:26:26
3.9K0
发布2020-01-03 11:26:26
举报
文章被收录于专栏:码农二狗码农二狗

前一段时间使用公司内部某个依赖共享内存的组件,其go版本api通过cgo提供。抛开我是个pure go狂热分子以外,采用cgo的方式实现会存在很多问题。所以分析其源码后通过go进行重写,故在此分享一下直接通过golang去操作共享内存。

通过golang操作共享内存主要依赖了以下几个系统调用:

  • SYS_SHMGET
  • SYS_SHMCTL
  • SYS_SHMAT
  • SYS_SHMDT

操作步骤:

1.根据shm key获取/创建共享内存:

代码语言:javascript
复制
shmid, _, err = syscall.Syscall(syscall.SYS_SHMGET, uintptr(key), uintptr(size), uintptr(mode&flags))
if err != 0 {
    return nil, errors.New(err.Error())
}

2.获取共享内存状态:

代码语言:javascript
复制
//from bits/ipc.h
type shmid_ds struct {
    ipc_perm struct {
        key     uint32
        uid     uint32
        gid     uint32
        cuid    uint32
        cgid    uint32
        mode    uint32
        pad1    uint16
        seq     uint16
        pad2    uint16
        unused1 uint
        unused2 uint
    }
    shm_segsz   uint32
    shm_atime   uint64
    shm_dtime   uint64
    shm_ctime   uint64
    shm_cpid    uint32
    shm_lpid    uint32
    shm_nattch  uint16
    shm_unused  uint16
    shm_unused2 uintptr
    shm_unused3 uintptr
}

shmid_ds = &shmid_ds{}
_, _, err = syscall.Syscall(syscall.SYS_SHMCTL, shmid, uintptr(IPC_STAT), uintptr(unsafe.Pointer(shmid_ds)))
if err != 0 {
    return nil, errors.New(err.Error())
}

3.映射共享内存地址到当前进程空间

代码语言:javascript
复制
addr, _, err = syscall.Syscall(syscall.SYS_SHMAT, shmid, 0, 0)
if err != 0 {
    return 0, errors.New(err.Error())
}

4.指针类型转换。完成该步骤后,操作的对象实际就是共享内存对象,需要自行控制data race。

代码语言:javascript
复制
attrs := (YourType)(unsafe.Pointer(uintptr(addr)))

5.将内存地址从当前进程空间分离,分离后对象将不可用

代码语言:javascript
复制
_, _, err = syscall.Syscall(syscall.SYS_SHMDT, addr, 0, 0)
if err != 0 {
    return errors.New(err.Error())
}

github地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档