本文实例分析了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语言程序设计有所帮助。
Go语言,共享内存,读写
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]