【Linux】進程的地址空間

再講進程的虛擬地址空間之前,我們先來了解一下程序的地址空間是什麼?

程序的地址空間

在這裏插入圖片描述
這是程序地址空間。而程序是一個個死的代碼,所以叫做程序地址空間不合適。程序運行起來之後,纔會佔用內存。所以我們稱爲進程地址空間
那麼我們思考一下,進程地址空間每一個進程都有一個,憑什麼每一個進程都會有4G的大小,那麼是內存不夠用的。

父子進程中的數據獨有,代碼共享,但是通過代碼實現可以在父子進程中實現對全局變量進行修改,也可以通過打印的方式看出父子進程中的同一變量的地址相同,那爲什麼一個一塊空間可以有兩個值 ?

其實,在程序中所獲得的變量地址都是假地址。因爲這個地址空間都是假的。所以我們叫它 進程的虛擬地址空間

進程虛擬地址空間的含義:

進程虛擬地址空間:是操作系統爲進程描述的一個假的地址空間。目的是爲了讓進程認爲自己擁有一塊連續的線性的完整的地址空間。但是實際上一個進程使用的內存並非連續存儲的,而是通過頁表映射了虛擬地址與物理地址之間的關係。爲了讓進程通過頁表獲取物理地址,進而實現數據的離散式存儲。

進程的虛擬地址空間的作用:

  1. 物理內存的離散式存儲,提高內存利用率

我們知道數據的對應關係,就可以離散式存儲,利用內存空間。但是程序運行起來還是需要連續的地址,操作系統爲一個程序提供一個線性虛擬的地址,在虛擬的地址中,程序的所有數據都是線性連續存儲,但是在物理內存中,程序運行時所要的數據都是離散式存儲的,所以操作系統在物理內存與虛擬內存之間建立了一個映射關係,提高了內存的利用率。
這個映射關係就是頁表。所以虛擬地址空間可以通過頁表直接映射到物理地址空間,這樣就可以尋找程序運行時所要的數據變量。

  1. 保證了進程的獨立性,每一個進程都只能訪問自己虛擬地址映射的物理內存

直接在物理內存上修改,不僅內存利用率低,而且會缺乏內存的訪問控制。大家都可以對同一塊內存上修改,這樣操作不安全,那麼就會缺乏訪問控制。

  1. 頁表可以進行內存的訪問控制,頁表可以對每個虛擬地址進行權限標記。
    1. 頁表中可以規定物理內存上的數據是否可以讀寫,頁表中若查到你要修改只讀數據,那麼就是內存訪問錯誤。
    2. 當對nullptr空指針訪問時,程序發生段錯誤。物理地址上0號位置實際上是有空間的。 其實nullptr是一個虛擬地址,當你訪問nullptr虛擬地址時,不能讀寫,是虛擬地址空間規定。
      進程的虛擬地址空間都是通過頁表來訪問自己映射的那塊內存,其它的程序不能訪問,這樣就保證進程之間相互獨立,獨立就代表着穩定。

我們接下來看父子進程中如何通過虛擬地址空間實現數據獨有?

虛擬地址空間其實也是我們描述出來的,通過mm_struct結構體(PCB),記錄每一個分區段的位置和大小,這個mm_struct * 也就是進程的內存指針 。因爲虛擬地址空間是靠很多區域的位置信息描述出來的,所以有時候也叫做內存描述符

進程之間爲什麼能通過虛擬地址空間空間實現數據獨有?

在這裏插入圖片描述

一開始的時候,通過PCB描述的進程1和進程2上的變量val都是100,在進程1和進程2的虛擬地址空間上都是相同的位置,所以我們在程序中看到的變量val的地址相同,其實是虛擬地址,假地址。此時通過頁表映射到物理內存中的相同位置,但是當進程1改變val值的時候,就不一樣了。

注意這裏的進程1和進程2也可以是父子進程

在這裏插入圖片描述
當進程1通過頁表映射要修改val值的時候,頁表會根據權限,知道進程1要修改數據,所以會先在物理內存上重新開一塊空間,並且將val值拷貝到新空間上,此時更新進程2的頁表映射,使進程2上的val值映射到物理內存上新的位置。在此過程中,進程1和進程2的虛擬地址空間上val的空間是不會改變的。所以進程間就實現了數據獨有。

寫時拷貝技術:等到需要更改數據時,再去申請內存,重新拷貝一份,並且更改頁表的對應關係。

寫時拷貝的原因是:提高進程創建的效率,有可能多個進程只是讀數據,並不修改這個數據。所以用的時候再去開闢新的內存,拷貝數據。提高效率。

我們再來捋一下如何創建子進程,使得數據獨有?
創建一個子進程的流程: 寫時拷貝技術

  1. 創建pcb
  2. 拷貝父進程中的pcb的數據(擁有相同的虛擬地址空間,相同的頁表)
  3. 父子進程一開始映射同一塊物理內存
  4. 等到物理內存修改時,才爲子進程重新開闢內存,拷貝數據。

爲什麼代碼共享而數據獨有
因爲進程的虛擬地址空間中代碼段是相同的,不會修改,所以一直映射同一塊物理內存中。

虛擬地址的構成:頁號 + 頁內偏移
頁面: 4096 物理內存:4G
所以一共有1024*1024個頁表項,頁表項也是結構體數組,如果一個頁表要開這麼大一個空間,那就太浪費了。因爲用不到這麼多的映射關係,所以就消耗資源。
二級頁表的引入
所以有了二級頁表,這塊頁表用到多少頁表項,這塊頁表的內存通過另一塊頁表來映射,用到了才爲頁表分配這塊內存,用不到就不分配了,提高內存利用率。

三種內存管理方式

內存管理:
分段式:對程序比較友好,但是內存利用率不高
分頁式:提高內存利用率
段頁式:目前採用的方案

分段式
在這裏插入圖片描述

分頁式
在這裏插入圖片描述
段頁式
在這裏插入圖片描述

物理地址的計算方法: 虛擬地址/頁面大小 = 頁號。 通過頁表得到塊號,塊號*塊大小 + 頁內偏移(虛擬地址%頁面大小)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章