源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Go语言共享内存读写实例分析

  • 时间:2021-09-03 02:55 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Go语言共享内存读写实例分析
本文实例分析了Go语言共享内存读写的方法。分享给大家供大家参考。具体分析如下: 前面分析了Go语言指针运算和内嵌C代码的方法,做了一个Go语言共享内存读写的实验。 先大概说下什么是共享内存。我们知道不同进程见的内存是互相独立的,没办法直接互相操作对方内的数据,而共享内存则是靠操作系统提供的内存映射机制,让不同进程的一块地址空间映射到同一个虚拟内存区域上,使不同的进程可以操作到一块共用的内存块。共享内存是效率最高的进程间通讯机制,因为数据不需要在内核和程序之间复制。 共享内存用到的是系统提供的mmap函数,它可以将一个文件映射到虚拟内存的一个区域中,程序使用指针引用这个区域,对这个内存区域的操作会被回写到文件上,Go内置的syscall包中有mmap函数,但是它是经过封装的,返回的是[]byte,没办法做我需求的指针运算,所以我还是用cgo来调用原生的mmap。 实验分为读和写两个程序,这样我们可以观察到读进程可以读到写进程写入共享内存的信息。 下面是shm_writer.go的代码:
[u]复制代码[/u] 代码如下:
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的代码:
[u]复制代码[/u] 代码如下:
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代码中有一行 :
[u]复制代码[/u] 代码如下:
#cgo linux LDFLAGS: -lrt
因为mmap在Mac上不需要连接librt,在linux上则需要,所以做了一个条件链接,这是cgo提供的功能。 上面代码中还用到一个cgo的技巧,像shm_open和mmap函数在错误时会返回errno,如果我们在go中使用多返回值语法,cgo会自己把错误码转换成错误信息,很方便的功能。 希望本文所述对大家的Go语言程序设计有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部