国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Golang > 正文

Go語言共享內(nèi)存讀寫實(shí)例分析

2020-04-01 19:19:04
字體:
供稿:網(wǎng)友
這篇文章主要介紹了Go語言共享內(nèi)存讀寫方法,實(shí)例分析了共享內(nèi)存的原理與讀寫技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
 

本文實(shí)例分析了Go語言共享內(nèi)存讀寫的方法。分享給大家供大家參考。具體分析如下:

前面分析了Go語言指針運(yùn)算和內(nèi)嵌C代碼的方法,做了一個(gè)Go語言共享內(nèi)存讀寫的實(shí)驗(yàn)。

先大概說下什么是共享內(nèi)存。我們知道不同進(jìn)程見的內(nèi)存是互相獨(dú)立的,沒辦法直接互相操作對(duì)方內(nèi)的數(shù)據(jù),而共享內(nèi)存則是靠操作系統(tǒng)提供的內(nèi)存映射機(jī)制,讓不同進(jìn)程的一塊地址空間映射到同一個(gè)虛擬內(nèi)存區(qū)域上,使不同的進(jìn)程可以操作到一塊共用的內(nèi)存塊。共享內(nèi)存是效率最高的進(jìn)程間通訊機(jī)制,因?yàn)閿?shù)據(jù)不需要在內(nèi)核和程序之間復(fù)制。

共享內(nèi)存用到的是系統(tǒng)提供的mmap函數(shù),它可以將一個(gè)文件映射到虛擬內(nèi)存的一個(gè)區(qū)域中,程序使用指針引用這個(gè)區(qū)域,對(duì)這個(gè)內(nèi)存區(qū)域的操作會(huì)被回寫到文件上,Go內(nèi)置的syscall包中有mmap函數(shù),但是它是經(jīng)過封裝的,返回的是[]byte,沒辦法做我需求的指針運(yùn)算,所以我還是用cgo來調(diào)用原生的mmap。

實(shí)驗(yàn)分為讀和寫兩個(gè)程序,這樣我們可以觀察到讀進(jìn)程可以讀到寫進(jìn)程寫入共享內(nèi)存的信息。

下面是shm_writer.go的代碼:

復(fù)制代碼代碼如下:
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的代碼:

復(fù)制代碼代碼如下:
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的虛擬內(nèi)存,用來證明mmap沒有實(shí)際占用4G內(nèi)存,而是用到了虛擬內(nèi)存。

shm_writer創(chuàng)建好共享內(nèi)存以后,往內(nèi)存區(qū)域?qū)懭肓艘粋€(gè)結(jié)構(gòu)體,shm_reader則讀出一個(gè)結(jié)構(gòu)體。

內(nèi)嵌的C代碼中有一行 :

復(fù)制代碼代碼如下:
#cgo linux LDFLAGS: -lrt

因?yàn)閙map在Mac上不需要連接librt,在linux上則需要,所以做了一個(gè)條件鏈接,這是cgo提供的功能。

 

上面代碼中還用到一個(gè)cgo的技巧,像shm_open和mmap函數(shù)在錯(cuò)誤時(shí)會(huì)返回errno,如果我們在go中使用多返回值語法,cgo會(huì)自己把錯(cuò)誤碼轉(zhuǎn)換成錯(cuò)誤信息,很方便的功能。

希望本文所述對(duì)大家的Go語言程序設(shè)計(jì)有所幫助。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 遵义县| 金秀| 浦北县| 庄河市| 岳阳县| 广元市| 政和县| 招远市| 砚山县| 安宁市| 天祝| 兴安县| 宽城| 吉安县| 沅江市| 隆回县| 云霄县| 商河县| 永泰县| 报价| 云安县| 莱州市| 澳门| 高邑县| 呼和浩特市| 靖西县| 大余县| 英山县| 贵溪市| 平舆县| 黔东| 宜兰县| 和硕县| 兰州市| 咸阳市| 蒙自县| 河东区| 科尔| 准格尔旗| 天柱县| 永昌县|