前面講了單純的操作系統的虛擬內存、linux進程的虛擬地址,然後又講了linux的進程的內存佈局,其實那張圖就是linux進程的虛擬內存。
可是感覺理解不夠,所以再來學習: 下面這部分是參考這個視頻學習的:
https://www.bilibili.com/video/av42496297?from=search&seid=1238971517368934147 這個說的是linux的 swap
這稱為交換過程。這樣你的linux系統就可以釋放一些ram空間,並且由於缺乏內存不會崩潰。因為 linux swap是擴展ram的一種非常有用的方法,因為它提供了必要的ram空間耗盡且必須繼續進程時的額外內存。所以這就是為什麼你安裝linux的時候會提示你要為交換linux內核通常使用RAM內存來存儲臨時信息,當沒有足夠的ram空間時,linux內核會從中獲取一些ram信息,並將其寫入硬碟驅動器上的交換空間。分區分配空間。如下圖:
我們需要linux swap嗎?
通常你的ram已滿並且linux內核沒有可寫空間時,你的系統將崩潰。但如果你有交換分區,那麼linux內核和程序會使用它,所以你的程序不會崩潰,可以繼續工作但是速度會慢很多。因此,擁有交換空間更安全。
交換分區有一個缺點:它比ram慢很多,因此,添加交換空間不會使你的計算機運行速度更快,它只會幫助克服一些ram大小帶來的限制。
交換空間有兩個選項:交換分區和交換文件。
交換分區是硬碟驅動器的一部分,他是為交換空間保留的。
交換分區的大小:
1g ram----2g swap
2-4g ram ----2-4g swap
8g ram ---- 4g swap
>8g -----2-4g swap
(我的win10是4g內存,8g虛擬內存,阿里雲上的linux swapon沒有反應)
我看完後發現,這個和虛擬內存的思想很像很像,可是又沒有確定的解釋它和linux的虛擬內存的關係。看來瞭解的還是太少了。
然後來看下一個視頻:這個內容不錯
學習於:https://www.bilibili.com/video/av32735338/
下面是核心圖:大家放大看會更好一些:
高級語言的程序代碼,經過編譯鏈接後,編程二進位的機器碼存儲在計算機的外存中。每個進程的代碼都有它的地址。這些機器指令序列是分頁存儲的,一般是4kb。就這樣一頁一頁地排在外存中。然後要運行的頁面就載入進內存中,不運行的就放在外存中。然後在每個進程的內核空間裏都存在著頁表,頁表裡存儲此進程的程序頁的編號,是否在內存,程序頁的在此進程中的虛擬地址,程序頁的物理內存地址,程序頁的外存地址。如果該程序頁在內存中,就沒有外存地址。
然後看cpu是怎麼執行指令的。
cpu運行一個進程的時候,要去取下一條指令的地址。這時候它收到的地址是進程傳過來的進程的虛擬地址,也就是說指令地址寄存器pc存放的是虛擬地址,然後經過MMU(memory manager unit)內存管理單元,MMU先通過該進程的頁表檢查指令所在頁是否在內存中,如果是,則直接去內存中去頁表裡的內存地址取出指令,然後執行。如果不在內存中,就去外存中找到該指令,把指令先載入到內存中,再將虛擬地址轉為內存地址,再從內存中取出指令執行,然後更新頁表。
這裡強調:虛擬內存是指針對cpu而言,cpu處理的是進程裏的虛擬地址,而不是操作具體的物理地址。也就是說cpu看到的是隻是虛擬地址,所以cpu認為這個虛擬地址對應這個內存,而這個內存是不存在的,所以我們認為這是虛擬內存。
(這位老師的說的頁面置換原則是隻要頁面沒運行,就置換出外存,而操作系統課上有很多的頁面置換演算法,比如LRU,FIFO之類的,這方面我不太清楚,但是這裡的思想感覺是沒錯的,也很細緻了)
至於缺頁中斷,tlb,局部性原理提高命中那方面的知識,前面的文章已經講過了,就不再這重複了。對了,這裡提醒一下,進程的內核空間應該是存儲在內存中的,而且各個進程的內核空間對應的都是內存中的同一個內核空間。裡面分別有各個進程的pcb,頁表等東西。
看完後我就產生了其它方面的疑問:置換出去的都是用戶空間的代碼段和數據段嗎?代碼段和數據段很大嗎?
下面是參考《深入理解計算機系統》:
虛擬內存的三個重要的能力:
1.它將主存看成是一個存儲在磁碟上的地址空間的高速緩存,在主存中只保存活動區域,並根據需要在磁碟和主存之間來回傳送數據,通過這種方式,它高效地使用了主存。
2.它為每個進程提供了一致的地址空間,從而簡化了內存管理。
3.它保護了每個進程的地址空間不被其它進程破壞。
後面看:騰訊雲技術社區:十問 Linux 虛擬內存管理 (glibc) (一) 又學到了一波東西。
這裡摘錄一些思考和筆記:
第一個理解:
進程使用多少內存可通過 ps aux 命令 查看,其中關鍵的兩信息(第五、六列)為:
然後結合圖片一看:
觀察一下,進程佔用的虛擬內存一般都多大,大的比如裡面的java進程是2.5個G 這樣,小的就幾十M,比如nginx的進程。而看實際物理內存,最大的就java的266M。這裡綜合一下4G的模型,所以在這裡理解都是4G是針對程序而言的,涉及到多級頁表的知識。
然後是下一個理解:
malloc 是 glibc 中內存分配函數,也是最常用的動態內存分配函數,其內存必須通過 free 進行釋放,否則導致內存泄露。
關於 malloc 獲得虛存空間的實現,與 glibc 的版本有關,但大體邏輯是:
其中 sbrk 就是修改棧頂指針位置,而 mmap 可用於生成文件的映射以及匿名頁面的內存,這裡指的是匿名頁面。
而這個 128k ,是 glibc 的默認配置
從這裡我們可以得到的信息是:內存分配和置換不只是指令代碼,還包括對象,數據之類的。只要是暫時沒用到的都可以把該page置換出去。
下一個理解:
疑問:究竟linux的虛擬內存的頁面置換演算法是怎麼實現的呢?似乎需要看源碼啊
嗯,差不多就到這裡吧。感覺還是得慢慢研究《深入理解計算機系統》這本書啊。這本書纔是權威,看網上的很多都不太靠譜。但是這本書有點難讀,後面慢慢來吧。。。
歡迎交流討論。