• <output id="aynwq"><form id="aynwq"><code id="aynwq"></code></form></output>

    <mark id="aynwq"><option id="aynwq"></option></mark>
  • <mark id="aynwq"><option id="aynwq"></option></mark><label id="aynwq"><dl id="aynwq"></dl></label>
  • 學(xué)習(xí)啦 > 學(xué)習(xí)電腦 > 網(wǎng)絡(luò)知識 > 網(wǎng)絡(luò)基礎(chǔ)知識 > 線性地址轉(zhuǎn)物理地址

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

    時間: 春健736 分享

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

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

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

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

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

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

      VOID

      MiInitMachineDependent (

      IN PLOADER_PARAMETER_BLOCK LoaderBlock

      )

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

      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);這句獲得一個頁表的指針。

      PDE_BASE是頁目錄的基址,這個宏的定義如下:(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或者開啟了PAE(奔騰往后都支持,默認(rèn)開啟),那么一個進(jìn)程頁目錄的基址為0xc0600000,這個在dbg調(diào)試的時候也可以看到,如

      kd> !pte 0000

      VA 00000000 (虛擬地址)

      PDE at C0600000 PTE at C0000000

      contains 0000000002B40067 contains 0000000000000000

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

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

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

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

      PdePageNumber = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);

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

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

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

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

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

      假如線性地址為7c920000,這個地址一般加載的是進(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,我們在windbg里看下,如下:

      kd> !pte 7c920000

      VA 7c920000

      PDE at C03007C8 PTE at C01F2480

      contains 03793067 contains 03791025

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

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

      PTE = 頁表基址+(頁目錄項索引 × 一個頁表的大小) + (頁表索引 × 每一個頁表項的大小)

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

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

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

      kd> dd C01F2480

      c01f2480 03791025 00000000 00000000 04157025

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

      到這里就算完了。

      補(bǔ)充:

      內(nèi)核定義的頁表的數(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;

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

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

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

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

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

    3.物理地址和虛擬地址

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

    5.物理地址可以改嗎

    603816 主站蜘蛛池模板: 日本黄页网站免费| 欧美人xxxx| 国产丰满肥熟在线观看| www.色天使| 日韩欧美中文字幕在线视频| 人妻少妇久久中文字幕| 都流了这么多还嘴硬| 国产精品第一页爽爽影院| 中文天堂在线www| 欧美性色欧美a在线观看| 午夜激情视频在线| 黄网站色视频免费看无下截| 在线a亚洲视频播放在线观看| 久久99精品久久久久婷婷| 欧美亚洲国产精品久久| 伸进大胸老师里面挤奶吃奶的频| 韩国大尺度床戏未删减版在线播放 | 色狠狠色狠狠综合天天| 国产精品成人免费视频电影| 一二三四社区在线中文视频| 日本香蕉一区二区三区| 亚洲国产精久久久久久久| 精产国品一二三产区M553| 国产乡下三级全黄三级| 2018狠狠干| 在车子颠簸中进了老师的身体| 中文在线最新版天堂| 日韩在线第一区| 亚洲午夜久久久精品影院| 狠狠色综合网久久久久久| 啊哈~在加了一根手指| 韩国色三级伦不卡高清在线观看| 国产精品美女久久久久AV福利| jizzjizz成熟丰满舒服| 把腿扒开做爽爽视频| 久久精品中文字幕大胸| 欧美亚洲国产丝袜在线| 亚洲永久网址在线观看| 男女午夜爽爽大片免费| 午夜老司机福利| 芭蕉私人影院在线观看|