• 企业400电话
  • 网络优化推广
  • AI电话机器人
  • 呼叫中心
  • 全 部 栏 目

    网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Go语言共享内存读写实例分析
    POST TIME:2021-10-18 17:48

    本文实例分析了Go语言共享内存读写的方法。分享给大家供大家参考。具体分析如下:

    前面分析了Go语言指针运算和内嵌C代码的方法,做了一个Go语言共享内存读写的实验。

    先大概说下什么是共享内存。我们知道不同进程见的内存是互相独立的,没办法直接互相操作对方内的数据,而共享内存则是靠操作系统提供的内存映射机制,让不同进程的一块地址空间映射到同一个虚拟内存区域上,使不同的进程可以操作到一块共用的内存块。共享内存是效率最高的进程间通讯机制,因为数据不需要在内核和程序之间复制。

    共享内存用到的是系统提供的mmap函数,它可以将一个文件映射到虚拟内存的一个区域中,程序使用指针引用这个区域,对这个内存区域的操作会被回写到文件上,Go内置的syscall包中有mmap函数,但是它是经过封装的,返回的是[]byte,没办法做我需求的指针运算,所以我还是用cgo来调用原生的mmap。

    实验分为读和写两个程序,这样我们可以观察到读进程可以读到写进程写入共享内存的信息。

    下面是shm_writer.go的代码:

    复制代码 代码如下:
    package main
    /*
    #cgo linux LDFLAGS: -lrt
    #include fcntl.h>
    #include unistd.h>
    #include sys/mman.h>
    #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);
    }
    */
    import "C"
    import (
        "fmt"
        "unsafe"
    )
    const SHM_NAME = "my_shm"
    const SHM_SIZE = 4 * 1000 * 1000 * 1000
    type MyData struct {
        Col1 int
        Col2 int
        Col3 int
    }
    func main() {
        fd, err := C.my_shm_new(C.CString(SHM_NAME))
        if err != nil {
            fmt.Println(err)
            return
        }
        C.ftruncate(fd, SHM_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
        }
        C.close(fd)
        data := (*MyData)(unsafe.Pointer(ptr))
        data.Col1 = 100
        data.Col2 = 876
        data.Col3 = 8021
    }

    下面是shm_reader.go的代码:

    复制代码 代码如下:
    package main
    /*
    #cgo linux LDFLAGS: -lrt
    #include fcntl.h>
    #include unistd.h>
    #include sys/mman.h>
    #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
    int my_shm_open(char *name) {
        return shm_open(name, O_RDWR);
    }
    */
    import "C"
    import (
        "fmt"
        "unsafe"
    )
    const SHM_NAME = "my_shm"
    const SHM_SIZE = 4 * 1000 * 1000 * 1000
    type MyData struct {
        Col1 int
        Col2 int
        Col3 int
    }
    func main() {
        fd, err := C.my_shm_open(C.CString(SHM_NAME))
        if err != nil {
            fmt.Println(err)
            return
        }
        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
        }
        C.close(fd)
        data := (*MyData)(unsafe.Pointer(ptr))
        fmt.Println(data)
    }

    上面的程序映射了一块4G的虚拟内存,用来证明mmap没有实际占用4G内存,而是用到了虚拟内存。

    shm_writer创建好共享内存以后,往内存区域写入了一个结构体,shm_reader则读出一个结构体。

    内嵌的C代码中有一行 :

    复制代码 代码如下:
    #cgo linux LDFLAGS: -lrt

    因为mmap在Mac上不需要连接librt,在linux上则需要,所以做了一个条件链接,这是cgo提供的功能。

    上面代码中还用到一个cgo的技巧,像shm_open和mmap函数在错误时会返回errno,如果我们在go中使用多返回值语法,cgo会自己把错误码转换成错误信息,很方便的功能。

    希望本文所述对大家的Go语言程序设计有所帮助。

    您可能感兴趣的文章:
    • Golang 内存模型详解(一)
    • Go语言中的Array、Slice、Map和Set使用详解
    • Go语言的GOPATH与工作目录详解
    • Go语言命令行操作命令详细介绍
    • Go语言interface详解
    • Go语言运行环境安装详细教程
    • Go语言实现简单的一个静态WEB服务器
    • GO语言并发编程之互斥锁、读写锁详解
    • GO语言标准错误处理机制error用法实例
    • Go语言中的内存布局详解
    上一篇:Go语言中嵌入C语言的方法
    下一篇:Go语言中的指针运算实例分析
  • 相关文章
  • 

    关于我们 | 付款方式 | 荣誉资质 | 业务提交 | 代理合作


    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    X

    截屏,微信识别二维码

    微信号:veteran88

    (点击微信号复制,添加好友)

     打开微信