14 [虛擬化] 虛存抽象;Linux進程的地址空間

14 [虛擬化] 虛存抽象;Linux進程的地址空間

南京大學操作系統課蔣炎巖老師網絡課程筆記。

視頻:https://www.bilibili.com/video/BV1N741177F5?p=14
講義:http://jyywiki.cn/OS/2021/slides/10.slides#/

本講概述

程序 = 狀態機;進程 = 狀態機的執行(路徑)

  • 狀態機的狀態由內存和寄存器(M,R)決定
    • 寄存器會在發生中斷之后保存到進程的內存(內核棧)中
    • 內存呢?

虛存抽象:

  • 進程的地址空間
  • 分頁機制
  • 分頁機制和虛擬存儲

進程的地址空間

進程的地址空間中有什么

進程的地址空間 = 內存中若干連續的 “段”,每一段是可訪問的(讀/寫/執行)的內存,可能映射到某個文件和 / 或在進程間共享。

進程執行指令需要代碼、數據、堆棧:

  • 代碼(如main,%rip會從此處取出待執行的指令)
  • 數據(如static int x)
  • 堆棧(如int y)

地址空間中還有:

  • 動態鏈接庫
  • 運行時分配的內存

以上這些都可以直接用指針訪問。

那么,這個地址空間是怎么創建的呢?創建之后,我們還可以修改它嗎?肯定是能的,如動態鏈接庫可以動態地加載。

管理進程地址空間的系統調用

// 映射
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);// 修改映射權限
int mprotect(void *addr, size_t length, int prot);

mmap的作用就是把磁盤文件的一部分直接映射到進程的內存中

說人話:在狀態機上增加或者刪除一段可訪問的內存。

把文件映射到地址空間?

它們好像的確沒什么區別:

  • 文件 = 字節序列
  • 內存 = 字節序列
  • 操作系統允許這樣映射好像挺合理的,下一課中,ELF loader用mmap非常容易實現,解析出要加載哪部分到內存,然后直接mmap就完了。

查看進程的地址空間

pmap

pmap命令可以查看某個進程的地址空間:

pmap [PID]

動態鏈接 / 靜態鏈接的地址空間

我們準備一個死循環C程序:

int main(){while (1);
}

分別用動態鏈接和靜態鏈接的方式來編譯它:

gcc test.c -o test_d.out
gcc -static test.c -o test_s.out

分別把得到的test_d.outtest_s.out后臺執行并用pmap來查看它們的地址空間:

$ ./test_d.out &
[1] 5002
$ ./test_s.out &
[2] 5015pmap 5002
pmap 5015

分別得到動態鏈接和靜態鏈接的pmap如下:

5002:   ./test_d.out
000055cfab135000      4K r-x-- test_d.out
000055cfab335000      4K r---- test_d.out
000055cfab336000      4K rw--- test_d.out
00007f26750a9000   1948K r-x-- libc-2.27.so
00007f2675290000   2048K ----- libc-2.27.so
00007f2675490000     16K r---- libc-2.27.so
00007f2675494000      8K rw--- libc-2.27.so
00007f2675496000     16K rw---   [ anon ]
00007f267549a000    164K r-x-- ld-2.27.so
00007f2675691000      8K rw---   [ anon ]
00007f26756c3000      4K r---- ld-2.27.so
00007f26756c4000      4K rw--- ld-2.27.so
00007f26756c5000      4K rw---   [ anon ]
00007fff1d64d000    132K rw---   [ stack ]
00007fff1d6cd000     12K r----   [ anon ]
00007fff1d6d0000      4K r-x--   [ anon ]
ffffffffff600000      4K --x--   [ anon ]total             4384K
5015:   ./test_s.out
0000000000400000    728K r-x-- test_s.out
00000000006b6000     24K rw--- test_s.out
00000000006bc000      4K rw---   [ anon ]
0000000000e17000    140K rw---   [ anon ]
00007fff1bf5b000    132K rw---   [ stack ]
00007fff1bfc5000     12K r----   [ anon ]
00007fff1bfc8000      4K r-x--   [ anon ]
ffffffffff600000      4K --x--   [ anon ]total             1048K

可以看到動態鏈接比靜態鏈接多了很多動態鏈接庫.so,占用的內存空間也較大。而通過ls -l命令,我們發現動態鏈接生成的可執行文件所占的磁盤空間更小。

pmap的實現

我們不禁好奇pmap是怎樣實現的,可以通過追蹤系統調用的strace工具來查看:

strace pmap 5002

實際上,我們多次強調過的一個概念:程序就是一個狀態機,而這樣一個狀態機想要得到操作系統里的任何東西,都要通過系統調用,所以當我們想知道pmap這樣的程序是怎樣實現的,最好的辦法就是去看一下它執行了哪些系統調用,因此說追蹤系統調用的strace工具是十分有用的

言歸正傳,上述pmap指令的輸出中最關鍵的是這一句:

openat(AT_FDCWD, "/proc/5002/maps", O_RDONLY) = 3

我們看到,pmap是去讀/proc文件中相關進程號的內存信息maps。(關于/proc:linux /proc 詳解)

我們發現了什么寶藏?

我們直接看一下上面動態鏈接的可執行文件的進程:

cat /proc/5--2/maps

輸出:

55cfab135000-55cfab136000 r-xp 00000000 103:02 28869833                  /home/song/CppProjects/test_d.out
55cfab335000-55cfab336000 r--p 00000000 103:02 28869833                  /home/song/CppProjects/test_d.out
55cfab336000-55cfab337000 rw-p 00001000 103:02 28869833                  /home/song/CppProjects/test_d.out
7f26750a9000-7f2675290000 r-xp 00000000 103:02 8393695                   /lib/x86_64-linux-gnu/libc-2.27.so
7f2675290000-7f2675490000 ---p 001e7000 103:02 8393695                   /lib/x86_64-linux-gnu/libc-2.27.so
7f2675490000-7f2675494000 r--p 001e7000 103:02 8393695                   /lib/x86_64-linux-gnu/libc-2.27.so
7f2675494000-7f2675496000 rw-p 001eb000 103:02 8393695                   /lib/x86_64-linux-gnu/libc-2.27.so
7f2675496000-7f267549a000 rw-p 00000000 00:00 0
7f267549a000-7f26754c3000 r-xp 00000000 103:02 8393690                   /lib/x86_64-linux-gnu/ld-2.27.so
7f2675691000-7f2675693000 rw-p 00000000 00:00 0
7f26756c3000-7f26756c4000 r--p 00029000 103:02 8393690                   /lib/x86_64-linux-gnu/ld-2.27.so
7f26756c4000-7f26756c5000 rw-p 0002a000 103:02 8393690                   /lib/x86_64-linux-gnu/ld-2.27.so
7f26756c5000-7f26756c6000 rw-p 00000000 00:00 0
7fff1d64d000-7fff1d66e000 rw-p 00000000 00:00 0                          [stack]
7fff1d6cd000-7fff1d6d0000 r--p 00000000 00:00 0                          [vvar]
7fff1d6d0000-7fff1d6d1000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

前面都好理解,是我們進程執行時的代碼、數據、堆棧、動態鏈接庫等,但是最后那三個:vvar、vdso、vsyscall是什么鬼?

vvar、vdso、vsyscall是什么鬼?

讓內核和進程共享數據 (內核可寫,進程只讀)

  • vvar: 內核和進程共享的數據

  • vdso: 系統調用代碼實現 (是操作系統的一部分)

  • vsyscall: (ffffffffff600000這么詭異的地址???)

  • 是普通系統調用的包裝

    • 曾經的 exception-less syscall 實現,但存在安全問題
    • 依然存在,保持向后兼容

vsyscall 的例子

  • 時間:內核維護秒級的時間 (所有進程映射同一個頁面)
    • 例子:time (2)
      • 我們甚至可以調試它
  • getcpu:per-CPU 映射頁面

計算機系統里沒有魔法!我們理解了 Linux 進程地址空間的全部!

使用共享內存與內核通信

有些系統調用不陷入內核也可以執行,使用共享內存和內核通信!

  • 內核線程在 spinning 等待系統調用的到來
  • 收到系統調用請求后立即開始執行
  • 進程 spin 等待系統調用完成
  • 如果系統調用很多,可以打包處理

實現虛擬存儲:分頁機制

需求分析

我們的操作系統看到的內存是真實的物理內存,而為各個線程提供的,即線程看到的是虛擬內存。那么,操作系統怎樣事項這一虛擬化呢?

操作系統希望實現地址空間的管理(mmap、munmap API)

  • 進程的地址空間是由若干 “段” 組成的,但是操作系統只擁有一個物理地址空間(物理內存)
  • 操作系統需要
    • 為進程存儲各個段的信息(例如在struct proc里)
    • 在物理內存中實際分配內存( pmm->alloc() )
    • 借助硬件的機制實現虛擬化 (CPU在執行用戶進程時,強制進行地址翻譯)

所以,我們需要一個函數 f:[0,M)→[0,M)f : [0,M) \rightarrow [0,M)f:[0,M)[0,M),把 ”虛擬地址“ 翻譯為 ”物理地址“ ,畢竟我們真實的物理內存只有一份,fff 應當由操作系統控制,即應用程序不可見 fff

操作系統為每個進程準備一個映射函數 fff ,當進程運行時,fff 被 ”加載“ 到CPU上,此后該進程每次訪問內存,都需要通過CPU上對應的 fff 來進行從該進程可見的虛擬內存到真實物理內存的映射,而該進程的任何越權訪問物理內存地址,都將觸發異常(缺頁?)。

應當注意,我們的 fff 有以下幾方面的要求:

  • 支持 fff 在運行時動態地進行修改(mmap,munmap)
  • 非常節約:fff 的存儲開銷必須遠小于實際使用的內存,總不能為了維護映射函數 fff 所使用的內存比實際要使用的內存還多
  • 非常高效:因為每次訪問內存都要計算 fff, 因此其實現需要非常高效

分頁機制

把地址空間切成大小為 ppp 的 “頁面” ,比如在x86中,頁面大小為4KiB。只維護以頁面為單位的映射,而非整個物理內存大小的虛擬內存到整個物理內存的映射。這樣我們要維護:[0,M/p)→[0,M/p)[0,M/p) \rightarrow [0,M/p)[0,M/p)[0,M/p) 的映射。

我們有這樣一個基本假設:進程內存地址的空間局部性,即絕大部分頁面都沒有映射,且映射一般都是連續的空間

Radix Tree(Trie) + TLB(Translation Lookaside Buffer)

在這里插入圖片描述

32位機和64位機的分頁尋址過程如圖所示:

在這里插入圖片描述
在這里插入圖片描述

分頁+保護:實現虛擬化

映射是頁面到頁面的,也就意味著映射的低位永遠是0,4kiB的頁面就會有12bits空閑,可以用來存儲頁面的存儲保護等信息。

在這里插入圖片描述

分頁機制與虛擬存儲

mmap并不需要為進程分配任何頁面,只需要 “讓操作系統知道這么映射” 就夠了,進程訪問頁面會進入缺頁進入操作系統。

操作系統并不需要在這一段創建的時候,就立即給進程分配內存,而是操作系統完全可以等到進程真正訪問這個頁面并發生缺頁時,再去分配這塊內存。當然,如果操作系統根據之前的映射發現進程訪問的這塊內存是不合法的,就會Segmentation Fault。

缺頁

缺頁時操作系統會得到缺頁的地址(%cr2),根據操作系統維護的進程地址信息分配頁面。

Memory-Mapped File:一致性

這樣的設計也有些問題需要明確,比如:

  • 如果把頁面映射到文件
    • 修改什么時候生效(立即生效,會造成大量的磁盤IO;等到unmap或者進程結束在生效,又太遲了)
    • 若干映射到同一個文件的進程(共享一份內存?各自有本地的副本?)

Takeaways and Wrap-up

虛擬化

  • 程序 = 狀態機 (進程的地址空間里到底有什么)
  • 操作系統 = 狀態機的管理者,借助硬件(物理狀態機)實現多個并發執行的虛擬狀態機(進程)
  • 狀態機中的地址空間(虛擬地址空間)
    • 應用視角:用mmap系統調用管理
    • 硬件視角:用分頁機制實現

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/532752.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/532752.shtml
英文地址,請注明出處:http://en.pswp.cn/news/532752.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瀏覽器是指在用戶計算機上,自考《網頁設計與制作》測試題及答案

自考《網頁設計與制作》測試題及答案學習是一個不斷積累的過程,為幫助考生們更好地復習《與制作》科目知識點,以下是搜索整理的一份自考《網頁設計與制作》測試題及答案,供參考練習,希望對大家有所幫助!想了解更多相關信息請持續關…

Ubuntu 18.04 安裝OpenCV C++

Ubuntu 18.04 安裝OpenCV C 構建并安裝 僅構建核心模塊 # 更新并安裝依賴 # 更新并安裝依賴 sudo apt update && sudo apt install -y cmake g wget unzip# 下載并解壓包 wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip unzip opencv.zip…

html計算x的y,HTML5畫布:旋轉時計算x,y點

我開發了一個HTML5 Canvas應用程序,它涉及到讀取一個xml文件,該文件描述了需要在畫布上繪制的箭頭,直形和其他形狀的位置。的XML布局的HTML5畫布:旋轉時計算x,y點實施例:如果對象被旋轉它涉及計算一個點的位…

(2021) 20 [虛擬化] 進程調度

(2021) 20 [虛擬化] 進程調度 南京大學操作系統課蔣炎巖老師網絡課程筆記。 視頻:https://www.bilibili.com/video/BV1HN41197Ko?p20 講義:http://jyywiki.cn/OS/2021/slides/11.slides#/ 背景 — 機制與策略分離 機制:一個通用的、可定制…

計算機組裝過程英文版,計算機組裝與維護試題及答案(國外英文資料).doc

計算機組裝與維護試題及答案(國外英文資料)計算機組裝與維護試題及答案(國外英文資料)(1) choiceIn the following equipment, the input device is (b)A. b. b. c. c. c. d. d.In Windows 98, the combination of CTRL Alt Del is (c)A. cold start b. heat start c. interr…

make命令及makefile

make命令及makefile 轉自:https://www.ruanyifeng.com/blog/2015/02/make.html Make 命令教程 作者: 阮一峰 日期: 2015年2月20日 代碼變成可執行文件,叫做編譯(compile);先編譯這個&#…

局域網中計算機網絡密碼查看,Win10怎么查看電腦上已知的wifi網絡密碼

方法一:網絡和共享中心查詢1、在Windows 10桌面最左下角的【Windwos開始圖標上右鍵】,在彈出的菜單中點擊打開【網絡連接】,如下圖所示。2、在打開的網絡連接設置中,雙擊已經連接的【無線網絡名稱】,在彈出的【WLAN狀態…

(2021) 22 [持久化] 1-Bit的存儲

(2021) 22 [持久化] 1-Bit的存儲 南京大學操作系統課蔣炎巖老師網絡課程筆記。 視頻:https://www.bilibili.com/video/BV1HN41197Ko?p22 講義:http://jyywiki.cn/OS/2021/slides/12.slides#/ 背景 回顧 操作系統是什么?一組對象 一組API…

計算機一級試題論述,計算機一級考試理論題及答案要點

計算機一級考試IT1必做題[1]. 著名的計算機科學家尼.沃思提出了________。A.數據結構+算法程序B.存儲控制結構C.信息熵D.控制論[2]. 下面有關掃描儀的敘述中,錯誤的是________。A.分辨率是掃描儀…

(2021) 23 [持久化] I/O設備與驅動

(2021) 23 [持久化] I/O設備與驅動 南京大學操作系統課蔣炎巖老師網絡課程筆記。 視頻:https://www.bilibili.com/video/BV1HN41197Ko?p23 講義:http://jyywiki.cn/OS/2021/slides/13.slides#/ 背景 很多人 (你們的同學們、家長們) 都有一個認識&…

計算機考研計劃時間,2019計算機考研時間安排:復習時間規劃

隨著考研競爭越來越激烈,考研復習一定要做好規劃,每天的時間要做好管理,分清輕重緩急,這樣才能高效率復習。管理的5個原則,大家抓緊調整個人復習。小編還為大家精心準備了計算機考研復習資料還有計算機考研報考指導助力…

(2021) 24 [持久化] 文件系統API

(2021) 24 [持久化] 文件系統API 南京大學操作系統課蔣炎巖老師網絡課程筆記。 視頻:https://www.bilibili.com/video/BV1HN41197Ko?p24 講義:http://jyywiki.cn/OS/2021/slides/14.slides#/ 背景 回顧 硬件視角:持久化的“層層抽象” 物…

計算機輔助應用的縮寫有什么,計算機輔助設計的英文縮寫是什么

2008-10-09是什么的英文縮寫?BOBO......頭型里的.....其實"BOBO頭"準確的名稱應該是BOB頭。它是娃娃頭的一種。BOB頭有許多變種,標準的類似于櫻桃小丸子的發型,專業發型師把它稱為BOB。最初是由巴黎發型師Antoine 在1909年發明,但…

Linux中的硬鏈接和軟鏈接

Linux中的硬鏈接和軟鏈接 節選自南大蔣炎巖老師操作系統網絡課程筆記:(2021) 24 [持久化] 文件系統API 硬(hard)鏈接 UNIX文件指針 在UNIX中,文件和目錄完全不是同一個概念,雖然我們平時看著它們仿佛并列地躺在某個…

計算機win10開機音樂,大師傳授win10系統電腦開機總是自動播放音樂的方案

今天小編分享一下win10系統電腦開機總是自動播放音樂問題的處理方法,在操作win10電腦的過程中常常不知道怎么去解決win10系統電腦開機總是自動播放音樂的問題,有什么好的方法去處理win10系統電腦開機總是自動播放音樂呢?今天本站小編教您怎么…

Linux中的tty、pts、pty等概念辨析

Linux中的tty、pts、pty等概念辨析 基本概念 tty、pty、pts、ptmx tty(終端設備的統稱):tty一詞源于Teletypes,或teletypewriters,原來指的是電傳打字機,是通過串行線用打印機鍵盤通過閱讀和發送信息的東…

(2021) 25 [持久化] 文件系統實現:FAT和UNIX文件系統

(2021) 25 [持久化] 文件系統實現:FAT和UNIX文件系統 南京大學操作系統課蔣炎巖老師網絡課程筆記。 視頻:https://www.bilibili.com/video/BV1HN41197Ko?p25 講義:http://jyywiki.cn/OS/2021/slides/15.slides#/ 背景 回顧 應用眼中的文件…

用計算機模擬地球誕生,計算機模擬顯示早期金星或像地球一樣宜居

雖然金星的綽號是“地球的邪惡孿生化身”,但它和地球上的一切都不同:灼熱、干燥并且被有毒煙云籠罩。不過,就在10億或20億年前,這兩個任性的“兄弟”可能更加相似。最新的計算機模擬顯示,早期的金星看上去和地球很像&a…

海南大學計算機原理,海南大學微機原理課件 第一章 計算機基礎知識

第一章計算機基礎知識數 制1.1一.計算機使用的數制及其相互轉換 十進制(D)、二進制(B)、八進制(O)和十六進制(H). 數制中用少量數碼按次序排列成數位,并按由低到高的進位方式進行計 數。(數碼的個數稱為基數) D---0,1,2,3,4,5,6,7,8,9------數碼十個(基為10)-------…

Linux中的二進制可執行文件和腳本可執行文件及Shebang

Linux中的二進制可執行文件和腳本可執行文件及Shebang 二進制可執行文件 我們知道&#xff0c;一個C程序經過預處理、編譯、匯編、鏈接就會得到一個二進制可執行文件&#xff0c;這種文件在Linux中叫做ELF文件。比如我們有一個C源代碼hello.c&#xff1a; #include <stdi…