導航:首頁 > 編程系統 > linux進程虛擬地址空間

linux進程虛擬地址空間

發布時間:2024-06-22 23:10:36

『壹』 linux進程虛擬地址空間的分布,以及堆和棧的區別

一、具體分布如圖所示:

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

『貳』 64位的linux上單個進程可以使用的最大內存數量是多少

對於64位Linux允許多達128個TB單個進程的虛擬地址空間,並且能夠解決大約64 TB的物理存儲器,但版是受處理器和系權統的限制。原話:64-bit Linux allows up to 128 TB of virtual address space for indivial processes, and can address approximately 64 TB of physical memory, subject to processor and system limitations.只要你的機器有足夠的內存統統可以給你放倒。連銀河曙光都能放下你的機器肯定不在話下:)而理論值更高,一個64位的微處理器可定址存儲器16 EB(1TB=1024GB,1PB=1024TB,1EB=1024PB自己換算)。順便說一下64位的windows企業伺服器最大2TB內存。

『叄』 Linux 的虛擬內存管理有幾個關鍵概念

Linux 的虛擬內存管理有幾個關鍵概念:
1、每個進程都有獨立的虛擬地址版空間,進程訪問權的虛擬地址並不是真正的物理地址;
2、虛擬地址可通過每個進程上的頁表(在每個進程的內核虛擬地址空間)與物理地址進行映射,獲得真正物理地址;
3、如果虛擬地址對應物理地址不在物理內存中,則產生缺頁中斷,真正分配物理地址,同時更新進程的頁表;如果此時物理內存已耗盡,則根據內存替換演算法淘汰部分頁面至物理磁碟中。

『肆』 linux 虛擬地址,到底怎麼理解

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

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

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

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

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

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

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

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

『伍』 linux:誰能給我解釋下虛擬地址和物理地址的聯系

這個問題很大。。。。我盡自己所能給你解釋一下吧,如果你不能完全看懂,以後可以回頭再翻翻來看。關於虛擬內存的事情,大概是這樣的:
首先你要明確什麼是虛擬內存。虛擬內存實際上是操作系統對於內存管理的一種方式,比如說,對每個程序而言,它的內存編址都從0x00到0xff,但是實際上,這些內存對應的物理地址,應用程序本身是無法知道的,在這里就可以理解成操作系統對內存管理的一層抽象。
比如,可能進程init的虛擬地址0x00對應了物理地址的0x10,而kthreadd的虛擬地址0x00對應物理地址0x20,etc.
而且虛擬內存也是一種有效的進程間隔離的方式,極大的提升了進程的安全性和操作系統的穩定性,也就是我一個進程不管做什麼,都是在它自己的地址空間里做的,不會影響到其他進程和OS。
當然這是理想情況,實際上還有進程間通信啦之類,這就不在這個問題的范圍之內了。
而具體怎麼把這些虛擬地址對應到物理地址上,這是操作系統做的事情,估計這個也就是你的問題。
----以上是背景1-----
然後我要明確一下:地址匯流排4位的意思是說內存用4個bit位來表達地址,所以能夠index的地址位就是2^0-2^4,也就是0x0到0xf,就是16個bit的內存空間。
然後我們再來細化一下你的例子,就比方說在你的16bit的內存的機器上有1個OS,上面跑著2個程序。一般來說OS會保留地址的高位,比如11-15bit的位置,作為kernel space;然後0-10bit是user space。
在以上的前提下,虛擬內存的效果是:在每一個程序看來,這個程序都有0x0到0xf的地址可以用,並且它們的0xb-0xf都是shared kernel space,然後0x0-0xa都是自己的user space,這樣彷彿就有了32個bit的地址一樣。這就是你所謂的是用虛擬地址可以使總的地址操作物理地址。至於os是怎麼做到這點的,繼續往下看。
-----以上是背景2-----
操作系統對每一個進程有一個進程式控制制塊,叫PCB,Process Control Block,里邊存儲了每一個進程的進程信息,比如說寄存器,file descriptor,還有我們最關心的內存映射信息。每一個進程有一個遞增的id號,叫pid,也就是Process IDentifier.
-----以上是背景3-----
進程間切換,也就是說,比如說你一個系統只有1個CPU,但是有兩個進程要跑,而且要讓我們看起來好像是兩個進程同時在跑一樣。為什麼我要提到這個呢,後面繼續看。
-----以上是背景4-----
好,現在來講如何把虛擬地址映射到物理地址。從程序的角度來看,從malloc開始講起,比如,在某一時刻,一個進程調用了malloc,在堆(heap)上申請了2bits的空間。實際上這個行為的流程是,程序調用malloc,進入內核模式之後,調用mmap,如果成功,操作系統會從物理地址上取一塊2bits的內存,交給應用程序編入虛擬地址空間。更詳細一點說,每個進程對內存管理是一個紅黑樹的結構,也就是說,在每一個進程的PCB,里維護了一顆紅黑樹,然後動態的將所有的新分配的內存加到這個紅黑樹里邊,以保證程序對每一塊內存的訪問時間是差不多的。然後不知道你們教材中有沒有提到頁表(page table),頁表也是PCB中的一項,你們教材中應該會對頁表有詳細的講解,將如何對內存的地址進行換算,之類的。然後你要明確,頁表實際上是紅黑樹的cache,這樣可以加速程序對於常用的內存的訪問速度。
以上是操作系統對內存管理的一個大致概括,就是一塊物理的內存如何映射成為一塊虛擬的內存。
我在背景2中說,兩個程序都看到自己有16個bit的虛擬地址,總共有32bit,但是實際上硬體只有16bits,也就是說,不管你在紅黑樹和頁表中怎麼映射,一定會有沖突發生,比如,可能物理地址的0x02對應了進程1中的0x04,又在進程2的PCB中映射到了pid2的虛擬地址位0x06上。操作系統如何解決這個矛盾呢,首先在進程pid 1運行的時候,這個0x02對應的是pid1中的0x04;然後這個時候進程切換發生了,pid 2開始運行。當pid2需要用到它的0x04時,os發現0x02這個地址在pid1中也有映射,於是它就把0x02這個地址上的內容存到硬碟上的一個叫swap的空間內,然後把這個地址交給pid2使用。這樣就達到了擴大虛擬地址的效果。
但是這樣做是有代價的,因為一旦這個page被swap出去,那麼在pid1再來調用的時候會發生一系列的miss,從L1 cache miss到 L2 cache miss到L3 cache miss,然後頁表miss,memory miss,會對程序的性能造成極大的影響。影響有多大呢,平均來說:
L1 cache hit: 0.5ns
L2 cache hit: 7ns
主內存引用:100ns
順序從內存中讀取1MB:250,000ns
硬碟尋道:10,000,000ns
從硬碟上順序讀取1MB:30,000,000ns
所以你就可以知道這種行為是以極大的性能為代價的。
----講完啦-----
總的來說這個很大的話題,我剛才所寫的東西的就是試圖讓你對虛擬內存這個東西有一個基本的概念,然後大致的了解內存是如何映射的。就我現在能想到的,對這個虛擬內存話題的討論還包括多級頁表,進程間隔離&通信以及memory fragment。
個人水平有限,如果以上有什麼地方說錯的或者遺漏的,還請各位多多補充和批評,謝謝。

『陸』 Linux下怎樣在進程中獲取虛擬地址對應的物理地址

Linux文件目錄中的/proc記錄著當前進程的信息,稱其為虛擬文件系統。在/proc下有一個鏈接目錄名為self,這意味著哪一個進程打開了它,self中存儲的信息就是所鏈接進程的。self中有一個名為page_map的文件,專門用來記錄所鏈接進程的物理頁號信息。這樣通過/proc/pid/page_map文件,允許一個用戶態的進程查看到每個虛擬頁映射到的物理頁

/proc/pid/page_map中的每一項都包含了一個64位的值,這個值內容如下所示。每一項的映射方式不同於真正的虛擬地址映射,其文件中遵循獨立的對應關系,即虛擬地址相對於0x0經過的頁面數是對應項在文件中的偏移量

* /proc/pid/pagemap. This file lets a userspace process find out which
physical frame each virtual page is mapped to. It contains one 64-bit
value for each virtual page, containing the following data (from
fs/proc/task_mmu.c, above pagemap_read):

* Bits 0-54 page frame number (PFN) if present//present為1時,bit0-54表示物理頁號
* Bits 0-4 swap type if swapped
* Bits 5-54 swap offset if swapped
* Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
* Bit 56 page exclusively mapped (since 4.2)
* Bits 57-60 zero
* Bit 61 page is file-page or shared-anon (since 3.5)
* Bit 62 page swapped
* Bit 63 page present//如果為1,表示當前物理頁在內存中;為0,表示當前物理頁不在內存中

在計算物理地址時,只需要找到虛擬地址的對應項,再通過對應項中的bit63判斷此物理頁是否在內存中,若在內存中則對應項中的物理頁號加上偏移地址,就能得到物理地址

通過程序獲取物理地址並驗證寫時拷貝技術

#include <stdio.h>


#include <stdlib.h>


#include <sys/types.h>


#include <unistd.h>


#include <sys/stat.h>


#include <fcntl.h>


#include <stdint.h>


//計算虛擬地址對應的地址,傳入虛擬地址vaddr,通過paddr傳出物理地址
void mem_addr(unsigned long vaddr, unsigned long *paddr)
{
int pageSize = getpagesize();//調用此函數獲取系統設定的頁面大小

unsigned long v_pageIndex = vaddr / pageSize;//計算此虛擬地址相對於0x0的經過的頁面數
unsigned long v_offset = v_pageIndex * sizeof(uint64_t);//計算在/proc/pid/page_map文件中的偏移量
unsigned long page_offset = vaddr % pageSize;//計算虛擬地址在頁面中的偏移量
uint64_t item = 0;//存儲對應項的值

int fd = open("/proc/self/pagemap", O_RDONLY);。。以只讀方式打開/proc/pid/page_map
if(fd == -1)//判斷是否打開失敗
{
printf("open /proc/self/pagemap error ");
return;
}

if(lseek(fd, v_offset, SEEK_SET) == -1)//將游標移動到相應位置,即對應項的起始地址且判斷是否移動失敗
{
printf("sleek error ");
return;
}

if(read(fd, &item, sizeof(uint64_t)) != sizeof(uint64_t))//讀取對應項的值,並存入item中,且判斷讀取數據位數是否正確
{
printf("read item error ");
return;
}

if((((uint64_t)1 << 63) & item) == 0)//判斷present是否為0
{
printf("page present is 0 ");
return ;
}

uint64_t phy_pageIndex = (((uint64_t)1 << 55) - 1) & item;//計算物理頁號,即取item的bit0-54

*paddr = (phy_pageIndex * pageSize) + page_offset;//再加上頁內偏移量就得到了物理地址
}

const int a = 100;//全局常量

int main()
{
int b = 100;//局部變數
static c = 100;//局部靜態變數
const int d = 100;//局部常量
char *str = "Hello World!";

unsigned long phy = 0;//物理地址

char *p = (char*)malloc(100);//動態內存

int pid = fork();//創建子進程
if(pid == 0)
{
//p[0] = '1';//子進程中修改動態內存
mem_addr((unsigned long)&a, &phy);
printf("pid = %d, virtual addr = %x , physical addr = %x ", getpid(), &a, phy);
}
else
{
mem_addr((unsigned long)&a, &phy);
printf("pid = %d, virtual addr = %x , physical addr = %x ", getpid(), &a, phy);
}

sleep(100);
free(p);
waitpid();
return 0;
}

測試結果如下:

全局常量:符合寫時拷貝技術

子進程修改動態內存

*其實想要知道虛擬地址對應的物理地址,通過這樣的方式也可以得到物理地址而不用操作MMU。。。*

以上就是Linux下怎樣在進程中獲取虛擬地址對應的物理地址的全文介紹,希望對您學習和使用linux系統開發有所幫助.

閱讀全文

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

熱點內容
用換機助手接收的軟體文件在哪找 瀏覽:282
閱達app一教一輔五年級有哪些 瀏覽:7
win10系統用f2調節音量 瀏覽:19
壓縮文件密碼器 瀏覽:840
線下活動數據分析有哪些 瀏覽:314
助聽器插片式編程線如何連接 瀏覽:293
怎麼刪除系統休眠文件 瀏覽:914
搜索文件內容中包含的文字並替換 瀏覽:542
微信相冊程序圖標 瀏覽:714
win8怎麼顯示文件格式 瀏覽:547
文件伺服器中毒 瀏覽:721
如何修改網站訪問次數 瀏覽:518
mdfldf是什麼文件 瀏覽:569
文件在桌面怎麼刪除干凈 瀏覽:439
馬蘭士67cd機版本 瀏覽:542
javaweb爬蟲程序 瀏覽:537
word中千位分隔符 瀏覽:392
迷你編程七天任務的地圖怎麼過 瀏覽:844
word2003格式不對 瀏覽:86
百度雲怎麼編輯文件在哪裡 瀏覽:304

友情鏈接