主頁(yè) > 知識(shí)庫(kù) > Go語(yǔ)言共享內(nèi)存讀寫實(shí)例分析

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

熱門標(biāo)簽:海外照相館地圖標(biāo)注入駐 經(jīng)常接到推銷電話機(jī)器人的電話 客服級(jí)電銷機(jī)器人 外呼系統(tǒng)多少錢一年 外呼系統(tǒng)如何接收服務(wù)密碼 智能營(yíng)銷軟件 旅游廁所如何電子地圖標(biāo)注 滁州自建外呼系統(tǒng) 工商信用卡外呼系統(tǒng)教程

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

前面分析了Go語(yǔ)言指針運(yùn)算和內(nèi)嵌C代碼的方法,做了一個(gè)Go語(yǔ)言共享內(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,如果我們?cè)趃o中使用多返回值語(yǔ)法,cgo會(huì)自己把錯(cuò)誤碼轉(zhuǎn)換成錯(cuò)誤信息,很方便的功能。

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

您可能感興趣的文章:
  • Golang 內(nèi)存模型詳解(一)
  • Go語(yǔ)言中的Array、Slice、Map和Set使用詳解
  • Go語(yǔ)言的GOPATH與工作目錄詳解
  • Go語(yǔ)言命令行操作命令詳細(xì)介紹
  • Go語(yǔ)言interface詳解
  • Go語(yǔ)言運(yùn)行環(huán)境安裝詳細(xì)教程
  • Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的一個(gè)靜態(tài)WEB服務(wù)器
  • GO語(yǔ)言并發(fā)編程之互斥鎖、讀寫鎖詳解
  • GO語(yǔ)言標(biāo)準(zhǔn)錯(cuò)誤處理機(jī)制error用法實(shí)例
  • Go語(yǔ)言中的內(nèi)存布局詳解

標(biāo)簽:深圳 楚雄 喀什 湘潭 九江 本溪 晉城 運(yùn)城

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Go語(yǔ)言共享內(nèi)存讀寫實(shí)例分析》,本文關(guān)鍵詞  語(yǔ)言,共享,內(nèi)存,讀寫,實(shí)例分析,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Go語(yǔ)言共享內(nèi)存讀寫實(shí)例分析》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于Go語(yǔ)言共享內(nèi)存讀寫實(shí)例分析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章