A. 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樹和紅黑樹很類似,但在插入和刪除節點方面,採用紅黑樹的性能更好一些,下面對紅黑樹給予簡單介紹。
一顆紅黑樹是具有以下特點的二叉樹:
每個節點著有顏色,或者為紅,或者為黑
根節點為黑色
如果一個節點為紅色,那麼它的子節點必須為黑色
從一個節點到葉子節點上的所有路徑都包含有相同的黑色節點數
B. 請教一道有關虛擬內存和虛擬地址空間的問題
1.運行的程序看你的系統性能是否夠好來確定(內存大小,CPU,顯卡等硬體性能)。
最多開到10來個程序再開也沒必要。
內存中容納程序 其實不是這樣說的。
比如一個QQ程序 將佔用30多MB內存。
一個IE 5-20內存/。(僅僅比如)
當你的程序開的超過你的內存容量和CPU處理能力時,你的計算機就會顯得比較慢 運行卡。
再開就基本會當機狀態,就是無法響應。
2。問題錯誤。
根本沒這個說法/。
虛擬內存是吧,比如一個計算機只配置256的物理內存條。在運行程序時就會顯得卡。因為使用完了物理內存,但是計算機又要繼續打開程序。
就會在硬碟里提取一部分空間虛擬為內存使用。
但是因為硬碟讀取速度比內存慢非常多。所以卡。
硬碟一般100MB/秒 內存 2000MB/秒以上
基本參數 雖然有些變動。但是對於生手也只能解釋到這樣程度了。
覺得卡 就加內存。CPU加不是太方便
C. 邏輯地址,物理地址,虛擬空間分別是什麼啊
接樓上的朋友
虛擬空間就是把一部分外存當做內存用。有時候內存滿了但是系統仍需要額外的空間放置進程,這時候會把一部分硬碟空間劃分為虛擬內存,這劃分的空間就是虛擬空間(語言不嚴謹大概就是這個意思)。
D. 虛擬內存與虛擬地址空間
windows下的虛擬內存指的是在硬碟上建一個文件,用來放置系統非活躍性內存數據或交換數據(怎麼放,放多少由操作系統決定)
虛擬地址空間,指windows下每個進程的私有內存空間,大小是4G,能訪問的是不到2G的空間,其餘是系統保留的.這2G是能訪問的,但並不是立即分配的,當進程使用多少時,才從物理內存中劃分給它多少,劃分的的方式是"映射",操作系統將虛擬內存的起始地址做個標記,標記成對應的物理內存的某個地址上.在這里,只有操作系統知道,進程是沒有任何辦法知道的,這是WINDOWS的高級內存管理機制決定的.物理內存的地址空間,只有操作系統才能訪問(硬體驅動也可以,但已經屬於系統低層了,進程是屬於用戶層)進程虛擬內存空間和物理內存空間的關系僅僅是看不見的映射關系.
虛擬內存通常只在系統物理內存用完時,才會使用到,但這個時候系統已經非常卡了.但也不是一點用處沒有,非活躍性進程的部分數據,系統是完全可以放在虛擬內存中的,
以上基於32位Windows系統.64位的沒去看過相關的資源,不清楚有沒有變動.
E. 虛擬內存與虛擬地址空間有什麼聯系
1、windows下的虛擬內存指的是在硬碟上建一個文件,用來放置系統非活躍性內存數據或交換數據(怎麼放,放多少由操作系統決定)。
2、虛擬地址空間,指windows下每個進程的私有內存空間,大小是4G,能訪問的是不到2G的空間,其餘是系統保留的.這2G是能訪問的,但並不是立即分配的,當進程使用多少時,才從物理內存中劃分給它多少,劃分的的方式是"映射",操作系統將虛擬內存的起始地址做個標記,標記成對應的物理內存的某個地址上.在這里,只有操作系統知道,進程是沒有任何辦法知道的。
3、這是WINDOWS的高級內存管理機制決定的.物理內存的地址空間,只有操作系統才能訪問(硬體驅動也可以,但已經屬於系統低層了,進程是屬於用戶層)進程虛擬內存空間和物理內存空間的關系僅僅是看不見的映射關系。
4、虛擬內存通常只在系統物理內存用完時,才會使用到,但這個時候系統已經非常卡了.但也不是一點用處沒有,非活躍性進程的部分數據,系統是完全可以放在虛擬內存中的。
5、以上基於32位Windows系統.64位的沒去看過相關的資源,不清楚有沒有變動。
F. 一般定址的地址空間 包括哪些存儲器 (緩存 ram rom flash 還有磁碟等) 在物理位置可能在哪裡 虛擬
賣家已很久沒和一年一年閆鳳嬌
G. 進程的地址空間就是虛擬地址空間!!可以這么理解么求大神。。
由於Windows程序時運行在386保護模式下,這樣程序訪問存儲器所使用的邏輯地址稱為虛擬地址,與實地址模式下的分段地址類似,虛擬地址也可以寫為「段:偏移量」的形式,這里的段是指段選擇器。
Windows 2000 使用基於分頁機制的虛擬內存。每個進程有4GB的虛擬地址空間。基於分頁機制,這4GB地址空間的一些部分被映射了物理內存,一些部分映射硬碟上的交換文件,一些部分什麼也沒有映射。程序中使用的都是4GB地址空間中的虛擬地址。而訪問物理內存,需要使用物理地址。
虛擬地址 (virtual address): 4G虛擬地址空間中的地址,程序中使用的都是虛擬地址。
如果CPU寄存器中的分頁標志位被設置,那麼執行內存操作的機器指令時,CPU會自動根據頁目錄和頁表中的信息,把虛擬地址轉換成物理地址,完成該指令。
H. 虛擬硬碟如何工作它的存儲空間來源於哪裡
虛擬硬碟是什麼鬼.................
如果你是指網吧的硬碟的話,用的都是伺服器的空間啊。
I. 關於線性地址和虛擬存儲空間
現在的磁碟,一直往存儲虛擬化方向發展,傳統意義上的硬碟分區,表示物理磁碟;比如C盤,D盤等。所謂虛擬存儲空間,是將你的物理磁碟做成虛擬化磁碟,舉個例子----
你的計算機D盤,安裝了一個WINDOWS2008操作系統,那麼這個磁碟就無法在安裝LINUX了,因為文件系統格式不一樣。那麼通過一些虛擬化軟體(比如VMWARE),可以將硬碟做成虛擬化狀態,在你的D盤上重新進行格式化,以文件的方式存儲操作系統,這樣可以裝多個OS了,而且管理方便,隨時刪除、復制。
J. 什麼是虛擬地址空間
虛擬地址
英文名稱為Virtual Address,簡稱VA,由於Windows程序時運行在386保護模式下,這樣程序訪問存儲器所使用的邏輯地址稱為虛擬地址,與實地址模式下的分段地址類似,虛擬地址也可以寫為「段:偏移量」的形式,這里的段是指段選擇器。 Windows 2000 使用基於分頁機制的虛擬內存。每個進程有4GB的虛擬地址空間。基於分頁機制,這4GB地址空間的一些部分被映射了物理內存,一些部分映射硬碟上的交換文件,一些部分什麼也沒有映射。程序中使用的都是4GB地址空間中的虛擬地址。而訪問物理內存,需要使用物理地址。 下面我們看看什麼是物理地址,什麼是虛擬地址。 物理地址 (physical address): 放在定址匯流排上的地址。放在定址匯流排上,如果是讀,電路根據這個地址每位的值就將相應地址的物理內存中的數據放到數據匯流排中傳輸。如果是寫,電路根據這個地址每位的值就將相應地址的物理內存中放入數據匯流排上的內容。物理內存是以位元組(8位)為單位編址的。 虛擬地址 (virtual address): 4G虛擬地址空間中的地址,程序中使用的都是虛擬地址。 如果CPU寄存器中的分頁標志位被設置,那麼執行內存操作的機器指令時,CPU會自動根據頁目錄和頁表中的信息,把虛擬地址轉換成物理地址,完成該指令。 比如 mov eax,004227b8h ,這是把地址004227b8h處的值賦給寄存器的匯編代碼,004227b8這個地址就是虛擬址。CPU在執行這行代碼時,發現寄存器中的分頁標志位已經被設定,就自動完成虛擬地址到物理地址的轉換,使用物理地址取出值,完成指令。對於Intel CPU 來說,分頁標志位是寄存器CR0的第31位,為1表示使用分頁,為0表示不使用分頁。對於初始化之後的 Win2k 我們觀察 CR0 ,發現第31位為1。表明Win2k是使用分頁的。 使用了分頁機制之後,4G的地址空間被分成了固定大小的頁,每一頁或者被映射到物理內存,或者被映射到硬碟上的交換文件中,或者沒有映射任何東西。對於一般程序來說,4G的地址空間,只有一小部分映射了物理內存,大片大片的部分是沒有映射任何東西。物理內存也被分頁,來映射地址空間。對於32bit的Win2k,頁的大小是4K位元組。CPU用來把虛擬地址轉換成物理地址的信息存放在叫做頁目錄和頁表的結構里。 物理內存分頁,一個物理頁的大小為4K位元組,第0個物理頁從物理地址 0x00000000 處開始。由於頁的大小為4KB,就是0x1000位元組,所以第1頁從物理地址 0x00001000 處開始。第2頁從物理地址 0x00002000 處開始。可以看到由於頁的大小是4KB,所以只需要32bit的地址中高20bit來定址物理頁。??? 頁表,一個頁表的大小為4K位元組,放在一個物理頁中。由1024個4位元組的頁表項組成。頁表項的大小為4個位元組(32bit),所以一個頁表中有1024個頁表項。頁表中的每一項的內容(每項4個位元組,32bit)高20bit用來放一個物理頁的物理地址,低12bit放著一些標志。 頁目錄,一個頁目錄大小為4K位元組,放在一個物理頁中。由1024個4位元組的頁目錄項組成。頁目錄項的大小為4個位元組(32bit),所以一個頁目錄中有1024個頁目錄項。頁目錄中的每一項的內容(每項4個位元組)高20bit用來放一個頁表(頁表放在一個物理頁中)的物理地址,低12bit放著一些標志。 對於x86系統,頁目錄的物理地址放在CPU的CR3寄存器中。 CPU把虛擬地址轉換成物理地址: 一個虛擬地址,大小4個位元組(32bit),包含著找到物理地址的信息,分為3個部分: 第22位到第31位這10位(最高10位)是頁目錄中的索引, 第12位到第21位這10位是頁表中的索引, 第0位到第11位這12位(低12位)是頁內偏移。 對於一個要轉換成物理地址的虛擬地址,CPU首先根據CR3中的值,找到頁目錄所在的物理頁。然後根據虛擬地址的第22位到第31位這10位(最高的10bit)的值作為索引,找到相應的頁目錄項(PDE,page directory entry),頁目錄項中有這個虛擬地址所對應頁表的物理地址。有了頁表的物理地址,根據虛擬地址的第12位到第21位這10位的值作為索引,找到該頁表中相應的頁表項(PTE,page table entry),頁表項中就有這個虛擬地址所對應物理頁的物理地址。最後用虛擬地址的最低12位,也就是頁內偏移,加上這個物理頁的物理地址,就得到了該虛擬地址所對應的物理地址。 一個頁目錄有1024項,虛擬地址最高的10bit剛好可以索引1024項(2的10次方等於1024)。一個頁表也有1024項,虛擬地址中間部分的10bit,剛好索引1024項。虛擬地址最低的12bit(2的12次方等於4096),作為頁內偏移,剛好可以索引4KB,也就是一個物理頁中的每個位元組。 一個虛擬地址轉換成物理地址的計算過程就是,處理器通過CR3找到當前頁目錄所在物理頁,取虛擬地址的高10bit,然後把這10bit右移2bit(因為每個頁目錄項4個位元組長,右移2bit相當於乘4)得到在該頁中的地址,取出該地址處PDE(4個位元組),就找到了該虛擬地址對應頁表所在物理頁,取虛擬地址第12位到第21位這10位,然後把這10bit右移2bit(因為每個頁表項4個位元組長,右移2bit相當於乘4)得到在該頁中的地址,取出該地址處的PTE(4個位元組),就找到了該虛擬地址對應物理頁的地址,最後加上12bit的頁內偏移得到了物理地址。 32bit的一個指針,可以定址范圍0x00000000-0xFFFFFFFF,4GB大小。也就是說一個32bit的指針可以定址整個4GB地址空間的每一個位元組。一個頁表項負責4K的地址空間和物理內存的映射,一個頁表1024項,也就是負責1024*4k=4M的地址空間的映射。一個頁目錄項,對應一個頁表。一個頁目錄有1024項,也就對應著1024個頁表,每個頁表負責4M地址空間的映射。1024個頁表負責1024*4M=4G的地址空間映射。一個進程有一個頁目錄。所以以頁為單位,頁目錄和頁表可以保證4G的地址空間中的每頁和物理內存的映射。 每個進程都有自己的4G地址空間,從 0x00000000-0xFFFFFFFF 。通過每個進程自己的一套頁目錄和頁表來實現。由於每個進程有自己的頁目錄和頁表,所以每個進程的地址空間映射的物理內存是不一樣的。兩個進程的同一個虛擬地址處(如果都有物理內存映射)的值一般是不同的,因為他們往往對應不同的物理頁。 4G地址空間中低2G,0x00000000-0x7FFFFFFF 是用戶地址空間,4G地址空間中高2G, 0x80000000-0xFFFFFFFF 是系統地址空間。訪問系統地址空間需要程序有ring0的許可權。