導航:首頁 > 操作系統 > linux虛擬地址空間

linux虛擬地址空間

發布時間:2022-06-08 04:31:15

linux 虛擬地址空間如何分布

一個進程的虛擬地址空間主要由兩個數據結來描述。一個是最高層次的:mm_struct,一個是較高層次的:vm_area_structs。最高層次的mm_struct結構描述了一個進程的整個虛擬地址空間。較高層次的結構vm_area_truct描述了虛擬地址空間的一個區間(簡稱虛擬區)。

1. MM_STRUCT結構

mm_strcut 用來描述一個進程的虛擬地址空間,在/include/linux/sched.h 中描述如下:

struct mm_struct {

struct vm_area_struct * mmap; /* 指向虛擬區間(VMA)鏈表 */

rb_root_t mm_rb; /*指向red_black樹*/

struct vm_area_struct * mmap_cache; /* 指向最近找到的虛擬區間*/

pgd_t * pgd; /*指向進程的頁目錄*/

atomic_t mm_users; /* 用戶空間中的有多少用戶*/

atomic_t mm_count; /* 對"struct mm_struct"有多少引用*/

int map_count; /* 虛擬區間的個數*/

struct rw_semaphore mmap_sem;

spinlock_t page_table_lock; /* 保護任務頁表和 mm->rss */

struct list_head mmlist; /*所有活動(active)mm的鏈表 */

unsigned long start_code, end_code, start_data, end_data;

unsigned long start_brk, brk, start_stack;

unsigned long arg_start, arg_end, env_start, env_end;

unsigned long rss, total_vm, locked_vm;

unsigned long def_flags;

unsigned long cpu_vm_mask;

unsigned long swap_address;

unsigned mpable:1;

/* Architecture-specific MM context */

mm_context_t context;

};

對該結構進一步說明如下:

在內核代碼中,指向這個數據結構的變數常常是mm。

每個進程只有一個mm_struct結構,在每個進程的task_struct結構中,有一個指向該進程的結構。可以說,mm_struct結構是對整個用戶空間的描述。

一個進程的虛擬空間中可能有多個虛擬區間(參見下面對vm_area_struct描述),對這些虛擬區間的組織方式有兩種,當虛擬區較少時採用單鏈表,由mmap指針指向這個鏈表,當虛擬區間多時採用「紅黑樹(red_black
tree)」結構,由mm_rb指向這顆樹。在2.4.10以前的版本中,採用的是AVL樹,因為與AVL樹相比,對紅黑樹進行操作的效率更高。

因為程序中用到的地址常常具有局部性,因此,最近一次用到的虛擬區間很可能下一次還要用到,因此,把最近用到的虛擬區間結構應當放入高速緩存,這個虛擬區間就由mmap_cache指向。

指針pgt指向該進程的頁目錄(每個進程都有自己的頁目錄,注意同內核頁目錄的區別),當調度程序調度一個程序運行時,就將這個地址轉成物理地址,並寫入控制寄存器(CR3)。

由於進程的虛擬空間及其下屬的虛擬區間有可能在不同的上下文中受到訪問,而這些訪問又必須互斥,所以在該結構中設置了用於P、V操作的信號量mmap_sem。此外,page_table_lock也是為類似的目的而設置。

雖然每個進程只有一個虛擬地址空間,但這個地址空間可以被別的進程來共享,如,子進程共享父進程的地址空間(也即共享mm_struct結構)。所以,用mm_user和mm_count進行計數。類型atomic_t實際上就是整數,但對這種整數的操作必須是「原子」的。

另外,還描述了代碼段、數據段、堆棧段、參數段以及環境段的起始地址和結束地址。這里的段是對程序的邏輯劃分,與我們前面所描述的段機制是不同的。

mm_context_t是與平台相關的一個結構,對i386 幾乎用處不大。

在後面對代碼的分析中對有些域給予進一步說明。

2. VM_AREA_STRUCT 結構

vm_area_struct描述進程的一個虛擬地址區間,在/include/linux/mm.h中描述如下:

struct vm_area_struct

struct mm_struct * vm_mm; /* 虛擬區間所在的地址空間*/

unsigned long vm_start; /* 在vm_mm中的起始地址*/

unsigned long vm_end; /*在vm_mm中的結束地址 */

/* linked list of VM areas per task, sorted by address */

struct vm_area_struct *vm_next;

pgprot_t vm_page_prot; /* 對這個虛擬區間的存取許可權 */

unsigned long vm_flags; /* 虛擬區間的標志. */

rb_node_t vm_rb;

/*

* For areas with an address space and backing store,

* one of the address_space->i_mmap{,shared} lists,

* for shm areas, the list of attaches, otherwise unused.

*/

struct vm_area_struct *vm_next_share;

struct vm_area_struct **vm_pprev_share;

/*對這個區間進行操作的函數 */

struct vm_operations_struct * vm_ops;

/* Information about our backing store: */

unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE

units, *not* PAGE_CACHE_SIZE */

struct file * vm_file; /* File we map to (can be NULL). */

unsigned long vm_raend; /* XXX: put full readahead info here. */

void * vm_private_data; /* was vm_pte (shared mem) */

};

vm_flag是描述對虛擬區間的操作的標志,其定義和描述如下

標志名 描述

VM_DENYWRITE 在這個區間映射一個打開後不能用來寫的文件。

VM_EXEC 頁可以被執行。

VM_EXECUTABLE 頁含有可執行代碼。

VM_GROWSDOWN 這個區間可以向低地址擴展。

VM_GROWSUP 這個區間可以向高地址擴展。

VM_IO 這個區間映射一個設備的I/O地址空間。

VM_LOCKED 頁被鎖住不能被交換出去。

VM_MAYEXEC VM_EXEC 標志可以被設置。

VM_MAYREAD VM_READ 標志可以被設置。

VM_MAYSHARE VM_SHARE 標志可以被設置。

VM_MAYWRITE VM_WRITE 標志可以被設置。

VM_READ 頁是可讀的。

VM_SHARED 頁可以被多個進程共享。

VM_SHM 頁用於IPC共享內存。
VM_WRITE 頁是可寫的。

較高層次的結構vm_area_structs是由雙向鏈表連接起來的,它們是按虛地址的降順序來排列的,每個這樣的結構都對應描述一個相鄰的地址空間范圍。之所以這樣分割,是因為每個虛擬區間可能來源不同,有的可能來自可執行映象,有的可能來自共享庫,而有的則可能是動態分配的內存區,所以對每一個由vm_area_structs結構所描述的區間的處理操作和它前後范圍的處理操作不同。因此Linux
把虛擬內存分割管理,並利用了虛擬內存處理常式(vm_ops)來抽象對不同來源虛擬內存的處理方法。不同的虛擬區間其處理操作可能不同,Linux在這里利用了面向對象的思想,即把一個虛擬區間看成一個對象,用vm_area_structs描述了這個對象的屬性,其中的vm_operation結構描述了在這個對象上的操作,其定義在/include/linux/mm.h中:

/*

* These are the virtual MM functions - opening of an area, closing and

* unmapping it (needed to keep files on disk up-to-date etc), pointer

* to the functions called when a no-page or a wp-page exception occurs.

*/

struct vm_operations_struct {

void (*open)(struct vm_area_struct * area);

void (*close)(struct vm_area_struct * area);

struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int unused);

};

vm_operations結構中包含的是函數指針;其中,open、close分別用於虛擬區間的打開、關閉,而nopage用於當虛存頁面不在物理內存而引起的「缺頁異常」時所應該調用的函數。

3.紅黑樹結構

Linux內核從2.4.10開始,對虛擬區的組織不再採用AVL樹,而是採用紅黑樹,這也是出於效率的考慮,雖然AVL樹和紅黑樹很類似,但在插入和刪除節點方面,採用紅黑樹的性能更好一些,下面對紅黑樹給予簡單介紹。
一顆紅黑樹是具有以下特點的二叉樹:
每個節點著有顏色,或者為紅,或者為黑
根節點為黑色
如果一個節點為紅色,那麼它的子節點必須為黑色
從一個節點到葉子節點上的所有路徑都包含有相同的黑色節點數

② Linux中4G的虛擬地址空間 最少需要多大的物理地址來映射

4G=4096M。一頁目錄表1024項,一個目錄項4M。一頁頁表4M,一個頁表項4K。

③ linux 64位系統每個進程擁有多大的虛擬內存

256T,內核128T 用戶128T

④ Linux進程虛擬地址空間的分布,以及堆和棧的區別

一、具體分布如圖所示:

二、關於堆和棧
(1)分配方式:
棧:由編譯器自動分配釋放,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧。
堆: 一般由程序員分配釋放,它的分配方式類似於鏈表。
(2)申請後系統的響應:
棧:只要所申請的空間小於棧的剩餘空間,則系統為程序分配內存,否則棧溢出。
堆:操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,遍歷該鏈表,找出第一個大於所申請空間的節點,然後將其從鏈表中刪除並分配,如果沒用完,則系統會把多餘的重新放回到鏈表中。
(3)申請大小的限制:
棧:棧是高地址向低地址擴展的連續內存,棧的大小一般是2M;
堆:堆是低地址向高地址擴展的不連續內存,堆的大小與計算機有效的虛擬內存有關系。
(4)申請效率:
棧:由系統自動分配,速度較快;
堆:速度慢,容易產生內存碎片;
關於Linux命令的介紹,看看《linux就該這么學》,具體關於這一章地址3w(dot)linuxprobe/chapter-02(dot)html.

⑤ linux下32位虛擬地址空間是多少

64位的linux採用4級頁表,支持的最大物理內存為64T。 對於虛擬地址空間的劃分,將0x0000,0000,0000,0000 – 0x0000,7fff,ffff,f000這128T地址用於用戶空間;而0xffff,8000,0000,0000以上的128T為系統空間地址。 具體的不是一兩句能說清楚了。

⑥ linux 虛擬地址,到底怎麼理解

不是僅僅 Linux 是這么設計的,整個現代流行的操作系統都是這么設計的。
應用程序被讀入內存後,為了保證系統的統一性,所有的程序都有同樣的一套定址規范。這個定址就是虛擬地址。這個虛擬地址是系統提供轉換的,不是程序的工作。

如果系統不提供這個功能,那麼應用程序就需要自己去尋找沒有被使用的內存,以及還要自己去處理內存容量的問題,而且如果程序調用外部的一些函數庫,這些函數庫也需要分配內存,這會導致應用程序的設計難度非常大,每個應用程序實際上就是一個操作系統了。多個程序共同運行導致內存使用混亂也很容易出現。
應用程序申請內存,使用的是操作系統的內存分配功能。這樣操作系統可以根據實際情況給應用程序內存,程序不需要考慮因為內存位置不同而必須不同編寫的難度。而且操作系統還可以提供虛擬內存等等各種方式來擴充內存,這樣的內存對於應用程序來說是不需要考慮的,一切都有系統打理。

使用虛擬地址後,對於應用程序來說,他的內存使用不需要考慮其他的程序佔用,也不需要考慮內存容量的問題,也不需要考慮內存塊位置,函數庫的調用也都扔給操作系統打理。這使得應用程序不需要考慮具體如何管理內存,只需要考慮作為應用程序的應用部分。

而且,因為內存是虛擬的,應用程序一些函數調用,操作系統可以把多個應用程序的調用都用同一套數據來處理,這樣,既可以節約內存使用(就是啟動100個應用程序,也只需要內存里有一套函數庫而已),也可以做到外部函數庫和應用程序沒有直接關聯,純粹是由系統做虛擬地址過渡。

至於為什麼 4G ,這是傳統+一些兼容的考慮。
以前沒有這個技術時,每個程序都可以完全使用整個系統,整個空間是連續的。到了這種虛擬地址的方式後,每個程序還是有自己「獨立」的一整套內存地址。但每個程序內存使用量肯定不一樣。那麼多少內存空間才完全夠用呢?當時因為正好使用了 32 位系統。那麼就把整個 32 位環境支持的 4G 內存容量作為這個極限。
不過因為內存地址是虛擬的。實際應用程序要用內存,是需要先申請的,所以只有程序申請後,真實內存才會被佔用。這個 4G 只是在演算法上作為極限。

不過因為 4G 也是硬體極限。所以 4G 以外的地址都是不能使用的,這就導致另一個問題,一些硬體有存儲器,有些硬體需要存儲空間做交互(比如 PCI ,比如各種硬體,比如 AGP 顯卡)。這些存儲區域怎麼處理?
所以,Windows Vista 的 32 位版在 4G 內存的機器上曾經報出只有 3.5G (有的機器甚至只有 3.25G 可以用)。就是這個問題的解決辦法導致的:把硬體的內存用虛擬地址的方式,放到虛擬地址的最後面。這樣應用程序調用硬體存儲時,可以直接按照內存的方式讀寫。這樣應用程序就很好的統一了存儲界面:只有 4G 的內存范圍,不存在其他方式的存儲調用方式(硬碟需要用讀寫功能讀取到內存後才能處理,而不是直接進行處理)。這樣應用程序的開發就很簡單,而且整個內存的使用每個程序都一樣。不存在各種硬體的原因而不同導致的需要重新設計內存管理演算法。操作系統也能根據實際應用程序的需要隨時分配數據,也可以根據每個程序的運行情況,區別的提供物理內存或者虛擬的內存。

這么設計最大的一個好處是,硬體環境和應用程序是無關的,中間由操作系統做轉換。而且應用程序互相之間也沒有影響,就好象整個內存都由他自己一個程序使用一樣。

PS:說了半天,我發現我自己也說不清楚其中的緣由……

⑦ linux的虛擬內存是4G,而每個進程都有自己獨立的4G內存空間,怎麼理解

一個進程用到的虛擬地址是由內存區域表來管理的,實際用不了4G。而用到的內存區域,會通過頁表映射到物理內存。所以每個進程都可以使用同樣的虛擬內存地址而不沖突,因為它們的物理地址實際上是不同的。

內核用的是3G以上的1G虛擬內存地址,其中896M是直接映射到物理地址的,128M按需映射896M以上的所謂高位內存。各進程用的是同一個內核,什麼叫「都運行內核」?

⑧ linux虛地址空間理論上的大小

在多任務操作系統中,每個進程都運行在屬於自己的內存沙盤中。這個沙盤就是虛擬地址空間(Virtual Address Space),在32位模式下它是一個4GB的內存地址塊。在Linux系統中, 內核進程和用戶進程所佔的虛擬內存比例是1:3,而Windows系統為2:2(通過設置Large-Address-Aware Executables標志也可為1:3)。這並不意味著內核使用那麼多物理內存,僅表示它可支配這部分地址空間,根據需要將其映射到物理內存。

虛擬地址通過頁表(Page Table)映射到物理內存,頁表由操作系統維護並被處理器引用。內核空間在頁表中擁有較高特權級,因此用戶態程序試圖訪問這些頁時會導致一個頁錯誤(page fault)。在Linux中,內核空間是持續存在的,並且在所有進程中都映射到同樣的物理內存。內核代碼和數據總是可定址,隨時准備處理中斷和系統調用。與此相反,用戶模式地址空間的映射隨進程切換的發生而不斷變化。

⑨ 對linux地址空間一段話的疑問

這個需要了解到操作系統的虛擬內存機制了。操作系統會在硬碟上開辟一塊空間,從邏輯上湊夠4G的內存地址。內存調度的時候,如果實際的物理內存中沒有載入到需要讀取的數據塊,則會從硬碟上另外開辟的那片swap空間找到,交換進實際物理內存中。

閱讀全文

與linux虛擬地址空間相關的資料

熱點內容
程序員知識架構體系 瀏覽:369
程序員專屬設計 瀏覽:517
單片機與sd卡 瀏覽:173
回家姑姑請程序員女友吃飯 瀏覽:824
php獲取代理ip 瀏覽:962
愛加密加固脫殼 瀏覽:566
win7將文件夾設置在桌面側邊 瀏覽:691
加密資產市值是多少 瀏覽:777
phpgraph 瀏覽:716
window10加密文件在哪裡 瀏覽:767
多看pro怎麼裝app 瀏覽:620
演算法的復雜度數包括 瀏覽:774
番茄小說app為什麼沒廣告 瀏覽:539
android系統的開機時間 瀏覽:20
android學習網站免費 瀏覽:827
單片機ic插腳 瀏覽:19
青山軟體找不到加密鎖 瀏覽:897
哪個app護膚品是正品又便宜 瀏覽:604
空氣壓縮機曲軸 瀏覽:990
伺服器託管是什麼業務 瀏覽:185