學(xué)習(xí)啦 > 學(xué)習(xí)電腦 > 網(wǎng)絡(luò)知識(shí) > 網(wǎng)絡(luò)基礎(chǔ)知識(shí) > 線(xiàn)性地址轉(zhuǎn)物理地址

線(xiàn)性地址轉(zhuǎn)物理地址

時(shí)間: 春健736 分享

線(xiàn)性地址轉(zhuǎn)物理地址

  邏輯地址,需要轉(zhuǎn)換成線(xiàn)性地址,再經(jīng)過(guò)MMU(CPU中的內(nèi)存管理單元)轉(zhuǎn)換成物理地址才能夠被訪(fǎng)問(wèn)到。那么線(xiàn)性地址怎么轉(zhuǎn)物理地址?今天學(xué)習(xí)啦小編整理了線(xiàn)性地址轉(zhuǎn)物理地址的相關(guān)資料,希望對(duì)大家有幫助。

  線(xiàn)性地址轉(zhuǎn)物理地址

  線(xiàn)性地址(Linear Address) 是邏輯地址到物理地址變換之間的中間層。程式代碼會(huì)產(chǎn)生邏輯地址,或說(shuō)是段中的偏移地址,加上相應(yīng)段的基地址就生成了一個(gè)線(xiàn)性地址。如果啟用了分頁(yè)機(jī)制,那么線(xiàn)性地址能再經(jīng)變換以產(chǎn)生一個(gè)物理地址。若沒(méi)有啟用分頁(yè)機(jī)制,那么線(xiàn)性地址直接就是物理地址。Intel 80386的線(xiàn)性地址空間容量為4G(2的32次方即32根地址總線(xiàn)尋址)。

  詳細(xì)說(shuō)下虛擬地址的轉(zhuǎn)換。

  首先,來(lái)看下內(nèi)核為一個(gè)進(jìn)程建立頁(yè)目錄和頁(yè)表以及線(xiàn)性空間的函數(shù)。這個(gè)函數(shù)原型是:

  VOID

  MiInitMachineDependent (

  IN PLOADER_PARAMETER_BLOCK LoaderBlock

  )

  位于init386.c的762行,這個(gè)函數(shù)太長(zhǎng)了,挑選部分如下:

  PointerPte = MiGetPdeAddress (PDE_BASE);

  PdePageNumber = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);

  CurrentProcess = PsGetCurrentProcess ();

  #if defined(_X86PAE_)

  PrototypePte.u.Soft.PageFileHigh = MI_PTE_LOOKUP_NEEDED;

  _asm {

  mov eax, cr3

  mov DirBase, eax

  }

  //

  // Note cr3 must be 32-byte aligned.

  //

  ASSERT ((DirBase & 0x1f) == 0);

  //

  // Initialize the PaeTop for this process right away.

  //

  RtlCopyMemory ((PVOID) &MiSystemPaeVa,

  (PVOID) (KSEG0_BASE | DirBase),

  sizeof (MiSystemPaeVa));

  CurrentProcess->PaeTop = &MiSystemPaeVa;

  #else

  DirBase = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) << PAGE_SHIFT;

  #endif

  CurrentProcess->Pcb.DirectoryTableBase[0] = DirBase;

  KeSweepDcache (FALSE);

  //

  // Unmap the low 2Gb of memory.

  //

  PointerPde = MiGetPdeAddress (0);

  LastPte = MiGetPdeAddress (KSEG0_BASE);

  MiZeroMemoryPte (PointerPde, LastPte - PointerPde);

  第一句:PointerPte = MiGetPdeAddress (PDE_BASE);這句獲得一個(gè)頁(yè)表的指針。

  PDE_BASE是頁(yè)目錄的基址,這個(gè)宏的定義如下:(i386.h 1968行)

  #define PDE_BASE_X86 0xc0300000

  #define PDE_BASE_X86PAE 0xc0600000

  #define PTE_TOP_X86 0xC03FFFFF

  #define PDE_TOP_X86 0xC0300FFF

  #define PTE_TOP_X86PAE 0xC07FFFFF

  #define PDE_TOP_X86PAE 0xC0603FFF

  #if !defined (_X86PAE_)

  #define PDE_BASE PDE_BASE_X86

  #define PTE_TOP PTE_TOP_X86

  #define PDE_TOP PDE_TOP_X86

  #else

  #define PDE_BASE PDE_BASE_X86PAE

  #define PTE_TOP PTE_TOP_X86PAE

  #define PDE_TOP PDE_TOP_X86PAE

  #endif

  #define PTE_BASE 0xc0000000

  可以看出,如果CPU支持PAE或者開(kāi)啟了PAE(奔騰往后都支持,默認(rèn)開(kāi)啟),那么一個(gè)進(jìn)程頁(yè)目錄的基址為0xc0600000,這個(gè)在dbg調(diào)試的時(shí)候也可以看到,如

  kd> !pte 0000

  VA 00000000 (虛擬地址)

  PDE at C0600000 PTE at C0000000

  contains 0000000002B40067 contains 0000000000000000

  pfn 2b40 ---DA--UWEV not valid

  再來(lái)看這個(gè)MiGetPdeAddress ,他是個(gè)宏,定義如下:(mi386.h 1889行)

  #define MiGetPdeAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))

  可以看出他是取線(xiàn)性地址的最高10位,再左移2位,加上頁(yè)目錄的基址,得到該線(xiàn)性地址在該進(jìn)程的 頁(yè)目錄的索引,而該處存放的就是其對(duì)應(yīng)的頁(yè)表索引,第二句:

  PdePageNumber = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);

  MI_GET_PAGE_FRAME_FROM_PTE 這個(gè)宏(mi386.h 2542行)的定義如下:

  #define MI_GET_PAGE_FRAME_FROM_PTE(PTE) ((PTE)->u.Hard.PageFrameNumber)

  他是直接取該頁(yè)表對(duì)應(yīng)的物理內(nèi)存的地址。到這里,CPU就可以訪(fǎng)問(wèn)到實(shí)際的物理內(nèi)存了。

  剩下的工作就是把cr3寄存器的內(nèi)容賦給dirbase,再把dirbase賦給進(jìn)程pcb的DirectoryTableBase項(xiàng),這個(gè)在windbg調(diào)試的時(shí)候我說(shuō)過(guò)了。后面再把該進(jìn)程的低2G的用戶(hù)空間清零。

  我舉個(gè)例子,咱來(lái)一步步轉(zhuǎn)換。(我關(guān)閉了PAE,關(guān)閉方法,網(wǎng)上找,xp sp3)

  假如線(xiàn)性地址為7c920000,這個(gè)地址一般加載的是進(jìn)程的ntdll文件,首先把它轉(zhuǎn)換成二進(jìn)制,我在windbg里做,如下:

  kd> .formats 7c920000

  Evaluate expression:

  Hex: 7c920000

  Decimal: 2089943040

  Octal: 17444400000

  Binary: 01111100 10010010 00000000 00000000

  Chars: |...

  Time: Mon Mar 24 11:44:00 2036

  Float: low 6.0646e+036 high 0

  Double: 1.03257e-314

  可以看到高10位為01111100 10十六進(jìn)制為0x1f2,

  01111100 10 ->0x1F2按照上面的宏,0x1F2在左移2位,為0x7C8,加上PDE的基址C0300000,結(jié)果為C03007C8,我們?cè)趙indbg里看下,如下:

  kd> !pte 7c920000

  VA 7c920000

  PDE at C03007C8 PTE at C01F2480

  contains 03793067 contains 03791025

  pfn 3793 ---DA--UWEV pfn 3791 ----A--UREV

  可以看到,結(jié)果是吻合的,下面我們來(lái)算頁(yè)表,按照上面的說(shuō)法,一個(gè)進(jìn)程的頁(yè)目錄可以達(dá)到1024項(xiàng)(2的10次方),而每項(xiàng)都是4字節(jié),所以一個(gè)進(jìn)程的頁(yè)目錄大小為4096bytes(4k),同理,一個(gè)頁(yè)表的大小也為4096bytes(4k),而每一個(gè)頁(yè)目錄項(xiàng)對(duì)應(yīng)一個(gè)4k大小的頁(yè)表,所以,頁(yè)表項(xiàng)的地址可以這么算:

  PTE = 頁(yè)表基址+(頁(yè)目錄項(xiàng)索引 × 一個(gè)頁(yè)表的大小) + (頁(yè)表索引 × 每一個(gè)頁(yè)表項(xiàng)的大小)

  由上面的宏定義知道在關(guān)了PAE的情況下頁(yè)表的基址PTE_BASE為0xc0000000,一個(gè)頁(yè)表項(xiàng)的大小也為4字節(jié)。而該線(xiàn)性地址的中間10位為010010 0000十六進(jìn)制為0x120,所以,該線(xiàn)性地址對(duì)應(yīng)的頁(yè)表地址為:

  PTE = 0xC0000000 + (0x1F2 * 0x1000) + (0x120 * 0x4) = 0xC01F2480.和上面windbg顯示的數(shù)據(jù)是一樣的。

  在windbg里看下該處的內(nèi)容為

  kd> dd C01F2480

  c01f2480 03791025 00000000 00000000 04157025

  該頁(yè)表處的內(nèi)容為0x03791025 ,其中,如果了解頁(yè)表結(jié)構(gòu)的話(huà),其高20位為該頁(yè)表指向的物理內(nèi)存,為0x3791,再加上線(xiàn)性地址的末12位偏移,所以該線(xiàn)性地址對(duì)應(yīng)的實(shí)際物理地址為:0X37910000.

  到這里就算完了。

  補(bǔ)充:

  內(nèi)核定義的頁(yè)表的數(shù)據(jù)結(jié)構(gòu)如下:

  typedef struct _MMPTE {

  union {

  ULONG Long;

  HARDWARE_PTE Flush;

  MMPTE_HARDWARE Hard;

  MMPTE_PROTOTYPE Proto;

  MMPTE_SOFTWARE Soft;

  MMPTE_TRANSITION Trans;

  MMPTE_SUBSECTION Subsect;

  MMPTE_LIST List;

  } u;

  } MMPTE;

  typedef MMPTE *PMMPTE;

  typedef struct _MMPTE_HARDWARE {

  ULONG Valid : 1;

  #if defined(NT_UP)

  ULONG Write : 1; // UP version

  #else

  ULONG Writable : 1; // changed for MP version

  #endif

  ULONG Owner : 1;

  ULONG WriteThrough : 1;

  ULONG CacheDisable : 1;

  ULONG Accessed : 1;

  ULONG Dirty : 1;

  ULONG LargePage : 1;

  ULONG Global : 1;

  ULONG CopyOnWrite : 1; // software field

  ULONG Prototype : 1; // software field

  #if defined(NT_UP)

  ULONG reserved : 1; // software field

  #else

  ULONG Write : 1; // software field - MP change

  #endif

  ULONG PageFrameNumber : 20;

  } MMPTE_HARDWARE, *PMMPTE_HARDWARE;

  可以看出上面那個(gè)取物理地址的宏直接取的就是PageFrameNumber ,也就是該地址內(nèi)容的高20位。

  而在!pte命令在還顯示了一些大些字母,如D,A,W,U之類(lèi)的,也在該結(jié)構(gòu)中有所顯示。

  看過(guò)“ 線(xiàn)性地址轉(zhuǎn)物理地址 ”的人還看了:

1.物理地址與虛擬地址怎么轉(zhuǎn)換

2.物理地址與虛擬地址映射

3.物理地址和虛擬地址

4.物理地址和邏輯地址的區(qū)別

5.物理地址可以改嗎

603816