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

作者:不是JS 时间:2024-05-21 10:20:02 

本文实例分析了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语言,内存,读写
0
投稿

猜你喜欢

  • jQuery打造动态渐变按钮

    2010-05-10 20:21:00
  • 浅谈anaconda python 版本对应关系

    2023-12-06 01:02:35
  • Vue组件设计之多列表拖拽交换排序功能实现

    2024-04-27 15:49:28
  • Python使用文件操作实现一个XX信息管理系统的示例

    2022-07-12 15:28:31
  • 彻底解决MySql在UTF8字符集下乱码问题

    2011-06-02 12:02:00
  • 如何彻底删除mysql服务(清理注册表)详解

    2024-01-28 18:16:34
  • JavaScript代码实现禁止右键、禁选择、禁粘贴、禁shift、禁ctrl、禁alt

    2024-04-18 09:39:57
  • MySQL5创建存储过程实例

    2010-06-13 12:49:00
  • Python实现爬取网页中动态加载的数据

    2021-08-11 18:35:27
  • python数据结构之搜索讲解

    2022-12-31 08:09:02
  • Python 八个数据清洗实例代码详解

    2022-12-08 23:50:36
  • Python+tkinter使用80行代码实现一个计算器实例

    2023-10-11 23:29:31
  • 使用Numpy读取CSV文件,并进行行列删除的操作方法

    2023-05-05 03:26:11
  • Django商城项目注册功能的实现

    2022-01-19 05:22:36
  • Python Web App开发Dockerfiles编写示例

    2023-02-01 12:47:19
  • python实现对象列表根据某个属性排序的方法详解

    2022-12-24 23:47:43
  • Python中struct模块对字节流/二进制流的操作教程

    2021-05-10 19:26:56
  • Python实现希尔排序算法的原理与用法实例分析

    2021-10-19 17:44:08
  • pyqt5 获取显示器的分辨率的方法

    2023-10-25 09:51:36
  • IE7的web标准之道 Ⅰ

    2008-08-13 12:42:00
  • asp之家 网络编程 m.aspxhome.com