當前位置:首頁 » 操作系統 » 虛擬地址物理地址linux

虛擬地址物理地址linux

發布時間: 2022-04-28 12:04:32

A. linux虛擬地址,地址映射表,物理內存與虛擬內存的關系

內存是一種存儲設備,現在一般是DDR SDRAM,地址是用來標記內存的數據的。在操作系統中物理內存指實際的DDR SDRAM,而虛擬內存指的是在硬碟中的緩存,windows中是頁面文件,linux中是swap分區。cpu產生的地址是虛擬地址也可以稱作有效地址,而在cpu外地址線上的信號稱作實際地址或物理地址。這2類地址有某種對應關系,由操作系統管理。如果是x86架構的話,物理地址和虛擬地址中間還有線性地址的概念。

B. 如何在LINUX中獲取進程中某個虛擬地址所在物理內

/*
*偽代碼,示例
*32位地址,三級映射(沒有pud_t),頁面大小4KB
*/
unsigned long addr = 0x12345678;//要找的虛擬地址,用戶空間所訪問的地址
unsigned long real_addr = 0x00;//要輸出的地址
struct task_struct *cur_task = get_current();//獲取當前進程式控制制塊
struct mm_struct *mm = cur_task -> mm;//進程虛擬空間
pgd_t *pgd;//描述頁全局目錄項
pmd_t *pmd;//描述頁中間項
pte_t *pte;//頁表項

pgd = pgd_offset(mm, addr);//找出所在目錄
if (pgd_none(*pgd)){
goto out;
}
pmd = pmd_offset(pgd, addr);//找出所在中間項

if (pmd_none(*pmd)){
goto out;
}
pte = pte_offset(pmd, addr);//找出所在頁面

if (pte_none(*pte)) {
goto out;
}

//假設每頁4KB
real_addr = addr & 0x00003fff; //取出頁面偏移量
real_addr += pte;//內核空間訪問的地址
real_addr -= PAGE_OFFSET;//真正物理地址()
printk("物理地址是 %x\n",real_addr);
return;

out:
printk("沒有內存映射",real_addr);

C. 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。
個人水平有限,如果以上有什麼地方說錯的或者遺漏的,還請各位多多補充和批評,謝謝。

D. 怎麼虛擬機-Linux機器的物理地址

假設網卡介面名稱為 eth0, 可以修改這個文件/etc/sysconfig/network-scripts/ifcfg-eth0

內容示例如下:

DEVICE="eth0"
HWADDR="18:03:73:F8:FB:B2"
#NM_CONTROLLED="yes"
ONBOOT="yes"
IPADDR="172.20.100.131"
NETMASK="255.255.0.0"
GATEWAY=172.20.254.251

修改上面的 HWADDR 即可,其為硬體地址。

E. 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系統開發有所幫助.

F. linux操作系統 虛擬地址問題 在學習操作系統時,經常會說程序員編寫程序使用的是虛擬地址空間,我

這個地址你%p 就能列印出來了
比如說系統有4G的空間,有1G是給內核的,3G是給用戶的,這3G裡面就包括靜態全局區、棧、堆、代碼區等
系統在運行一個程序時,會先將硬碟的程序上傳到內存的代碼段然後執行,在遇到局部變數時,系統會在棧里為它開辟一塊空間存儲數據,遇到全局或靜態變數就會在靜態全局區開辟一塊空間用來存儲數據,這些都是系統為我們自動分配的地址,而用戶也可以自己分配地址存儲數據
例如:
int *p = (int *)0;
*p = 123;
這樣我們就將整形數據123存儲在0地址上了
你說的程序對應的虛擬地址,你將程序反匯編,我記得那裡面就有每一條指令的地址,主函數入口的地址就是你程序對應的虛擬地址

G. linux中虛擬地址和物理地址怎樣映射

虛擬就是虛擬的,不是實際真是的物理地址。你可以認為,這兩個地址之間沒關系。
這個虛擬是通過系統和硬體的雙重工作,做的一種點對點的映射(當然實際內存分配是按照頁來處理)。
也就是軟體不需要考慮內存數據的物理地址,只需要用虛擬地址做數據存儲處理就行了。

這樣一個好處是,軟體不需要自己做內存分配,也不需要考慮別的軟體的內存佔用問題。操作系統會根據當前的內存使用情況,動態的分配內存空間。虛擬內存地址還一個好處是因為是虛擬的,所以內存並不一定非要在物理內存中。可以存放在任何位置,比如把暫時不用的數據放進硬碟上的虛擬內存,騰出真實的物理內存交給程序運行而提高多程序時運行的效率。而且因為每個軟體的虛擬內存地址都是從 0 開始,每個軟體的定址都是獨立而且順序的。程序編寫和運行時,都好像是機器裡面只有自己一個程序在運行,程序開發起來也很容易。軟體不需要考慮內存分配的問題,也不需要擔心內存不足和兩個程序搶同一片內存導致系統整個崩潰的情況。

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

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

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

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

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

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

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

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

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

I. linux 內核中物理地址轉換為虛擬地址一些不懂的地方,麻煩指點

  1. GPFCON 0X56000050
    GPFDAT 0x56000054
    GPFUP 0x56000058
    Reserved 0x5600005c

這是四個連續的物理地址,每個長度為4位元組,所以是16


2. 在 32位系統上, sizeof(指針) 是4,所以 sizeof(xxxx xxxx *) 總是等於4,由於gpfcon 指向的是被映射後的0X56000050, gpfdata 就指向0x56000054

熱點內容
如何不斷攻擊http伺服器 發布:2024-10-04 17:07:35 瀏覽:311
如何更換5e伺服器 發布:2024-10-04 17:03:02 瀏覽:218
java微博系統源碼 發布:2024-10-04 16:36:58 瀏覽:540
出國訪問計劃 發布:2024-10-04 15:52:34 瀏覽:565
編程實數類型 發布:2024-10-04 15:42:18 瀏覽:243
sqlite3打開資料庫 發布:2024-10-04 15:37:29 瀏覽:766
python創建數據表 發布:2024-10-04 15:33:12 瀏覽:756
需要美國IP的雲伺服器哪家好 發布:2024-10-04 15:32:21 瀏覽:525
手機玩死亡交換的伺服器是什麼 發布:2024-10-04 15:30:32 瀏覽:362
360app加密 發布:2024-10-04 15:21:23 瀏覽:983