中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang的內存介紹

發布時間:2020-05-29 13:41:36 來源:億速云 閱讀:294 作者:鴿子 欄目:編程語言

前言

  • 總的來說一個程序的生命周期可以概括為: 編寫代碼 => 編譯 => 鏈接 => 加載到內存 => 執行

  • 在本文中,我們將對內存進行簡單介紹

  • 內存

  • 在計算機中,術語"內存"又叫做主存,通常指的是可尋址的半導體存儲器(硅基MOS晶體管組成的集成電路)

  • 內存有易失性(volatile)和非易失性兩種,非易失性內存主要用于存儲特殊的程序(例如BIOS),易失性內存通常指的是隨機存儲器(random-access memory,RAM)

  • RAM是計算機數據存儲的一種形式,用于存儲當前正在使用的數據和機器碼

  • RAM允許在幾乎相同的時間內讀取或寫入數據項,而不管數據在內存中的位置

  • 我們可以將物理內存視為如下的插槽/單元陣列,一個插槽可容納8位的信息。每個內存插槽都有一個地址,CPU可以通過尋址讀取或者寫入特定地址的數據

golang的內存介紹

  • 計算機通常運行多個任務,直接操作物理內存將是非常危險的(例如某程序讀取所有數據、或者A程序修改了B程序在內存中的數據)

  • 因此,為了不直接操作物理內存,出現了虛擬內存的技術。通過虛擬內存,間接的操作物理內存

虛擬內存

golang的內存介紹

  • 擁有虛擬內存之后,程序運行時,它只會訪問自己接觸過的內存。同時,并非所有的數據都需要存儲在RAM中。操作系統可以通過將一部分空閑的RAM置換到速度較慢的存儲設備(例如磁盤)中,從而節省寶貴的RAM,獲得更大的內存空間

  • 可以根據CPU架構和操作系統絕對虛擬內存的實現細節,但是大部分采用的是分頁表(Paged Virtual Memory)的形式來實現。在分頁虛擬內存中,我們將虛擬內存分割為稱為的塊

  • 頁的大小可能會因硬件而異,但通常為4-64 KB,通常可以使用2 MB至1 GB的大頁。劃分塊很有用,避免了使用更多的內存來單獨管理每個內存插槽,從而提升計算機的性能

  • 為了實現分頁虛擬內存,有一種稱為內存管理單元(MMU)的芯片,它位于CPU和物理內存之間,MMU將虛擬內存地址到物理內存地址的映射保存在稱為頁表(page table)的表中(該表存儲在內存中),每頁包含一個“頁表項”(Page Table Entry,PTE).MMU還有叫做Translation Lookaside Buffer (TLB)的物理緩存,用于存儲從虛擬內存到物理內存的最新轉換

golang的內存介紹

假設操作系統將一部分虛擬內存頁放入了磁盤中,程序嘗試訪問它,則程序會發生以下過程:

  • 1、CPU發出訪問虛擬地址的命令,MMU在頁面表中檢查該地址后禁止訪問,因為尚未為該虛擬頁面分配物理RAM

  • 2、然后,MMU將頁錯誤發送到CPU

  • 3、然后,操作系統通過查找RAM的備用存儲塊(稱為frame)并設置新的PTE進行映射來處理Page錯誤

  • 4、如果沒有可用的RAM,則可以使用某種替換算法將現有頁面保存到磁盤(此過程稱為頁面調度(paging))

  • 操作系統通常管理多個應用程序(進程),因此整個內存管理如下:

golang的內存介紹

  • 每個進程都有一個線性虛擬地址空間,地址從0到某個最大值。虛擬地址空間不必是連續的,因此并非所有這些虛擬地址都實際用于存儲數據,也不會占用RAM或磁盤中的空間

  • 虛擬內存強大之處在于,同一塊物理內存可以對應于多個進程的多個虛擬內存頁

程序加載

  • 在上面,我們概述了什么是內存以及如何實現硬件和操作系統相互通信

  • 為了運行程序,操作系統具有一個模塊,用于加載程序和所需的庫,稱為程序加載器。在Linux中,您可以使用execve()系統調用從程序中調用程序加載器

  • 加載程序運行時,將通過以下步驟

    • 驗證程序(權限,內存要求等)

    • 將程序從磁盤復制到主存儲器

    • 傳遞命令行參數

    • 初始化寄存器(如棧指針)


  • 加載完成后,操作系統通過將控制權傳遞給加載的程序代碼來啟動程序(執行跳轉指令到程序的入口點)

  • 在之前文章,我們介紹了go build 編譯可以生成可執行文件和不可執行的obj文件。這些文件通常都擁有通用的格式,例如在linux中為ELF(Executable and Linkable Format)格式文件,在windows中為PE(Portable Executable)格式文件

  • 有時,無法用Go編寫所有內容。在這種情況下,一種選擇是手工制作自己的ELF二進制文件并將機器代碼放入正確的ELF結構中。obj文件包含多個部分 .text (可執行代碼), .data (全局變量), and .rodata (全局常量)

  • 在Go中,我們可以輕松地編寫一個程序來讀取ELF可執行文件,因為Go在標準庫中有一個debug/elf包.如下例所示:

package main

import (
    "debug/elf"
    "log"
)

func main() {
    f, err := elf.Open("main")

    if err != nil {
        log.Fatal(err)
    }

    for _, section := range f.Sections {
        log.Println(section)
    }
}
  • 輸出如下

2020/02/18 20:54:16 &{{ SHT_NULL 0x0 0 0 0 0 0 0 0 0} 0xc00006e390 0xc00006e390 0 0}
2020/02/18 20:54:16 &{{.text SHT_PROGBITS SHF_ALLOC+SHF_EXECINSTR 4198400 4096 715732 0 0 16 0 715732} 0xc00006e3c0 0xc00006e3c0 0 0}
2020/02/18 20:54:16 &{{.rodata SHT_PROGBITS SHF_ALLOC 4915200 720896 389824 0 0 32 0 389824} 0xc00006e3f0 0xc00006e3f0 0 0}
2020/02/18 20:54:16 &{{.shstrtab SHT_STRTAB 0x0 0 1110720 417 0 0 1 0 417} 0xc00006e420 0xc00006e420 0 0}
2020/02/18 20:54:16 &{{.typelink SHT_PROGBITS SHF_ALLOC 5305472 1111168 3784 0 0 32 0 3784} 0xc00006e450 0xc00006e450 0 0}
2020/02/18 20:54:16 &{{.itablink SHT_PROGBITS SHF_ALLOC 5309256 1114952 248 0 0 8 0 248} 0xc00006e480 0xc00006e480 0 0}
2020/02/18 20:54:16 &{{.gosymtab SHT_PROGBITS SHF_ALLOC 5309504 1115200 0 0 0 1 0 0} 0xc00006e4b0 0xc00006e4b0 0 0}
2020/02/18 20:54:16 &{{.gopclntab SHT_PROGBITS SHF_ALLOC 5309504 1115200 527028 0 0 32 0 527028} 0xc00006e4e0 0xc00006e4e0 0 0}
2020/02/18 20:54:16 &{{.go.buildinfo SHT_PROGBITS SHF_WRITE+SHF_ALLOC 5836800 1642496 32 0 0 16 0 32} 0xc00006e510 0xc00006e510 0 0}
2020/02/18 20:54:16 &{{.noptrdata SHT_PROGBITS SHF_WRITE+SHF_ALLOC 5836832 1642528 55000 0 0 32 0 55000} 0xc00006e540 0xc00006e540 0 0}
2020/02/18 20:54:16 &{{.data SHT_PROGBITS SHF_WRITE+SHF_ALLOC 5891840 1697536 36464 0 0 32 0 36464} 0xc00006e570 0xc00006e570 0 0}
2020/02/18 20:54:16 &{{.bss SHT_NOBITS SHF_WRITE+SHF_ALLOC 5928320 1734016 115376 0 0 32 0 115376} 0xc00006e5a0 0xc00006e5a0 0 0}
2020/02/18 20:54:16 &{{.noptrbss SHT_NOBITS SHF_WRITE+SHF_ALLOC 6043712 1849408 10152 0 0 32 0 10152} 0xc00006e5d0 0xc00006e5d0 0 0}
2020/02/18 20:54:16 &{{.zdebug_abbrev SHT_PROGBITS 0x0 6053888 1736704 281 0 0 8 0 281} 0xc00006e600 0xc00006e600 0 0}
2020/02/18 20:54:16 &{{.zdebug_line SHT_PROGBITS 0x0 6054169 1736985 107844 0 0 8 0 107844} 0xc00006e630 0xc00006e630 0 0}
2020/02/18 20:54:16 &{{.zdebug_frame SHT_PROGBITS 0x0 6162013 1844829 29529 0 0 8 0 29529} 0xc0000b6000 0xc0000b6000 0 0}
2020/02/18 20:54:16 &{{.zdebug_pubnames SHT_PROGBITS 0x0 6191542 1874358 5947 0 0 8 0 5947} 0xc0000b6030 0xc0000b6030 0 0}
2020/02/18 20:54:16 &{{.zdebug_pubtypes SHT_PROGBITS 0x0 6197489 1880305 15217 0 0 8 0 15217} 0xc00006e660 0xc00006e660 0 0}
2020/02/18 20:54:16 &{{.debug_gdb_scripts SHT_PROGBITS 0x0 6212706 1895522 42 0 0 1 0 42} 0xc0000b6060 0xc0000b6060 0 0}
2020/02/18 20:54:16 &{{.zdebug_info SHT_PROGBITS 0x0 6212748 1895564 234437 0 0 8 0 234437} 0xc0000b6090 0xc0000b6090 0 0}
2020/02/18 20:54:16 &{{.zdebug_loc SHT_PROGBITS 0x0 6447185 2130001 108898 0 0 8 0 108898} 0xc00006e690 0xc00006e690 0 0}
2020/02/18 20:54:16 &{{.zdebug_ranges SHT_PROGBITS 0x0 6556083 2238899 38294 0 0 8 0 38294} 0xc0000b60c0 0xc0000b60c0 0 0}
2020/02/18 20:54:16 &{{.note.go.buildid SHT_NOTE SHF_ALLOC 4198300 3996 100 0 0 4 0 100} 0xc0000b60f0 0xc0000b60f0 0 0}
2020/02/18 20:54:16 &{{.symtab SHT_SYMTAB 0x0 0 2277376 75168 24 118 8 24 75168} 0xc0000b6120 0xc0000b6120 0 0}
2020/02/18 20:54:16 &{{.strtab SHT_STRTAB 0x0 0 2352544 80179 0 0 1 0 80179} 0xc00006e6c0 0xc00006e6c0 0 0}
  • 可以使用Linux工具查看ELF文件,例如size --format=sysv main 或者 readelf -l main

  • 如上所示,可執行文件只是具有某種預定義格式的文件。通常,可執行格式擁有許多段(segements),這些段是在運行程序之前映射的數據存儲塊。通常認為,程序具有如下格式

golang的內存介紹

  • text段包含程序的指令,文字和靜態常量

  • data段數據段通常是指用來存放程序中已初始化且不為0的全局變量的一塊內存區域,它可以由exec預分配和預加載,并且進程可以擴展或收縮它

  • stack段包含一個程序棧。它隨著棧的增長而增長,但是不會隨著棧的收縮而收縮

  • heap區通常從.bss和.data段的末尾開始,并從那里開始增長到更大的地址。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

于都县| 梧州市| 濉溪县| 昌邑市| 河池市| 宾阳县| 湖北省| 芦溪县| 涞水县| 浪卡子县| 会泽县| 九寨沟县| 胶南市| 西安市| 微博| 曲水县| 唐山市| 东平县| 平远县| 凉山| 莒南县| 阳西县| 德庆县| 亚东县| 海南省| 蒲江县| 岳阳市| 忻城县| 曲水县| 南丹县| 大竹县| 临夏县| 潼南县| 远安县| 龙门县| 宝丰县| 科技| 东光县| 融水| 徐闻县| 方山县|