国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

驅(qū)動(dòng)開發(fā):內(nèi)核物理內(nèi)存尋址讀寫

這篇具有很好參考價(jià)值的文章主要介紹了驅(qū)動(dòng)開發(fā):內(nèi)核物理內(nèi)存尋址讀寫。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

在某些時(shí)候我們需要讀寫的進(jìn)程可能存在虛擬內(nèi)存保護(hù)機(jī)制,在該機(jī)制下用戶的CR3以及MDL讀寫將直接失效,從而導(dǎo)致無法讀取到正確的數(shù)據(jù),本章我們將繼續(xù)研究如何實(shí)現(xiàn)物理級(jí)別的尋址讀寫。

首先,驅(qū)動(dòng)中的物理頁讀寫是指在驅(qū)動(dòng)中直接讀寫物理內(nèi)存頁(而不是虛擬內(nèi)存頁)。這種方式的優(yōu)點(diǎn)是它能夠更快地訪問內(nèi)存,因?yàn)樗苊饬颂摂M內(nèi)存管理的開銷,通過直接讀寫物理內(nèi)存,驅(qū)動(dòng)程序可以繞過虛擬內(nèi)存的保護(hù)機(jī)制,獲得對系統(tǒng)中內(nèi)存的更高級(jí)別的訪問權(quán)限。

想要實(shí)現(xiàn)物理頁讀寫,第一步則是需要找到UserDirectoryTableBase的實(shí)際偏移地址,你一定會(huì)問這是個(gè)什么?別著急,聽我來慢慢解釋;

在操作系統(tǒng)中,每個(gè)進(jìn)程都有一個(gè)KPROCESS結(jié)構(gòu)體,它是進(jìn)程的內(nèi)部表示。該結(jié)構(gòu)體中包含了一些重要的信息,包括UserDirectoryTableBase字段,它指向進(jìn)程的頁表目錄表(Page Directory Table),也稱為DirectoryTable頁目錄表。

Page Directory Table是一種數(shù)據(jù)結(jié)構(gòu),它在虛擬內(nèi)存管理中起著重要的作用。它被用來存儲(chǔ)將虛擬地址映射到物理地址的映射關(guān)系,其內(nèi)部包含了一些指向頁表的指針,每個(gè)頁表中又包含了一些指向物理頁面的指針。這些指針一起構(gòu)成了一個(gè)樹形結(jié)構(gòu),它被稱為頁表樹(Page Table Tree)。

kd> dt _KPROCESS
ntdll!_KPROCESS
+0x278 UserTime         : Uint4B
+0x27c ReadyTime        : Uint4B
+0x280 UserDirectoryTableBase : Uint8B
+0x288 AddressPolicy    : UChar
+0x289 Spare2           : [71] UChar

#define GetDirectoryTableOffset 0x280

UserDirectoryTableBase字段包含了進(jìn)程的頁表樹的根節(jié)點(diǎn)的物理地址,通過它可以找到進(jìn)程的頁表樹,從而實(shí)現(xiàn)虛擬內(nèi)存的管理。在WinDbg中,通過輸入dt _KPROCESS可以查看進(jìn)程的KPROCESS結(jié)構(gòu)體的定義,從而找到UserDirectoryTableBase字段的偏移量,這樣可以獲取該字段在內(nèi)存中的地址,進(jìn)而獲取DirectoryTable的地址。不同操作系統(tǒng)的KPROCESS結(jié)構(gòu)體定義可能會(huì)有所不同,因此它們的UserDirectoryTableBase字段的偏移量也會(huì)不同。

通過上述原理解釋,我們可知要實(shí)現(xiàn)物理頁讀寫需要實(shí)現(xiàn)一個(gè)轉(zhuǎn)換函數(shù),因?yàn)樵趹?yīng)用層傳入的還是一個(gè)虛擬地址,通過TransformationCR3函數(shù)即可實(shí)現(xiàn)將虛擬地址轉(zhuǎn)換到物理地址,函數(shù)內(nèi)部實(shí)現(xiàn)了從虛擬地址到物理地址的轉(zhuǎn)換過程,并返回物理地址。

// 從用戶層虛擬地址切換到物理頁地址的函數(shù)
// 將 CR3 寄存器的末尾4個(gè)比特清零,這些比特是用于對齊的,不需要考慮
/*
    參數(shù) cr3:物理地址。
    參數(shù) VirtualAddress:虛擬地址。
*/
ULONG64 TransformationCR3(ULONG64 cr3, ULONG64 VirtualAddress)
{
  cr3 &= ~0xf;
  // 獲取頁面偏移量
  ULONG64 PAGE_OFFSET = VirtualAddress & ~(~0ul << 12);

  // 讀取虛擬地址所在的三級(jí)頁表項(xiàng)
  SIZE_T BytesTransferred = 0;
  ULONG64 a = 0, b = 0, c = 0;

  ReadPhysicalAddress((PVOID)(cr3 + 8 * ((VirtualAddress >> 39) & (0x1ffll))), &a, sizeof(a), &BytesTransferred);

  // 如果 P(存在位)為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~a & 1)
  {
    return 0;
  }

  // 讀取虛擬地址所在的二級(jí)頁表項(xiàng)
  ReadPhysicalAddress((PVOID)((a & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 30) & (0x1ffll))), &b, sizeof(b), &BytesTransferred);

  // 如果 P 為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~b & 1)
  {
    return 0;
  }

  // 如果 PS(頁面大?。?,表示該頁表項(xiàng)映射的是1GB的物理內(nèi)存,直接計(jì)算出物理地址并返回
  if (b & 0x80)
  {
    return (b & (~0ull << 42 >> 12)) + (VirtualAddress & ~(~0ull << 30));
  }

  // 讀取虛擬地址所在的一級(jí)頁表項(xiàng)
  ReadPhysicalAddress((PVOID)((b & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 21) & (0x1ffll))), &c, sizeof(c), &BytesTransferred);

  // 如果 P 為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~c & 1)
  {
    return 0;
  }
  // 如果 PS 為1,表示該頁表項(xiàng)映射的是2MB的物理內(nèi)存,直接計(jì)算出物理地址并返回
  if (c & 0x80)
  {
    return (c & ((~0xfull << 8) & 0xfffffffffull)) + (VirtualAddress & ~(~0ull << 21));
  }
  // 讀取虛擬地址所在的零級(jí)頁表項(xiàng),計(jì)算出物理地址并返回
  ULONG64 address = 0;
  ReadPhysicalAddress((PVOID)((c & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 12) & (0x1ffll))), &address, sizeof(address), &BytesTransferred);
  address &= ((~0xfull << 8) & 0xfffffffffull);
  if (!address)
  {
    return 0;
  }

  return address + PAGE_OFFSET;
}

這段代碼將輸入的CR3值和虛擬地址作為參數(shù),并將CR3值和虛擬地址的偏移量進(jìn)行一系列計(jì)算,最終得出物理地址。

其中,CR3是存儲(chǔ)頁表的物理地址,它保存了虛擬地址到物理地址的映射關(guān)系。該函數(shù)通過讀取CR3中存儲(chǔ)的頁表信息,逐級(jí)訪問頁表,直到找到對應(yīng)的物理地址。

該函數(shù)使用虛擬地址的高9位確定頁表的索引,然后通過讀取對應(yīng)的頁表項(xiàng),得到下一級(jí)頁表的物理地址。該過程重復(fù)執(zhí)行,直到讀取到頁表的最后一級(jí),得到物理地址。

最后,該函數(shù)將物理地址的低12位與虛擬地址的偏移量進(jìn)行OR運(yùn)算,得到最終的物理地址,并將其返回。

需要注意的是,該函數(shù)還會(huì)進(jìn)行一些錯(cuò)誤處理,例如在讀取頁表項(xiàng)時(shí),如果該項(xiàng)沒有被設(shè)置為有效,函數(shù)將返回0,表示無法訪問對應(yīng)的物理地址。

此時(shí)用戶已經(jīng)獲取到了物理地址,那么讀寫就變得很容易了,當(dāng)需要讀取數(shù)據(jù)時(shí)調(diào)用ReadPhysicalAddress函數(shù),其內(nèi)部直接使用MmCopyMemory對內(nèi)存進(jìn)行拷貝即可,而對于寫入數(shù)據(jù)而言,需要通過調(diào)用MmMapIoSpace先將物理地址轉(zhuǎn)換為一個(gè)用戶空間的虛擬地址,然后再通過RtlCopyMemory向內(nèi)部拷貝數(shù)據(jù)即可實(shí)現(xiàn)寫入,這三段代碼的封裝如下所示;

#include <ntifs.h>
#include <windef.h>

#define GetDirectoryTableOffset 0x280
#define bit64 0x28
#define bit32 0x18

// 讀取物理內(nèi)存封裝
// 這段代碼實(shí)現(xiàn)了將物理地址映射到內(nèi)核空間,然后將物理地址對應(yīng)的數(shù)據(jù)讀取到指定的緩沖區(qū)中。
/*
    address:需要讀取的物理地址;
    buffer:讀取到的數(shù)據(jù)需要保存到的緩沖區(qū);
    size:需要讀取的數(shù)據(jù)大小;
    BytesTransferred:實(shí)際讀取到的數(shù)據(jù)大小。
*/
NTSTATUS ReadPhysicalAddress(PVOID address, PVOID buffer, SIZE_T size, SIZE_T* BytesTransferred)
{
  MM_COPY_ADDRESS Read = { 0 };
  Read.PhysicalAddress.QuadPart = (LONG64)address;
  return MmCopyMemory(buffer, Read, size, MM_COPY_MEMORY_PHYSICAL, BytesTransferred);
}

// 寫入物理內(nèi)存
// 這段代碼實(shí)現(xiàn)了將數(shù)據(jù)寫入物理地址的功能
/*
    參數(shù) address:要寫入的物理地址。
    參數(shù) buffer:要寫入的數(shù)據(jù)緩沖區(qū)。
    參數(shù) size:要寫入的數(shù)據(jù)長度。
    參數(shù) BytesTransferred:實(shí)際寫入的數(shù)據(jù)長度。
*/
NTSTATUS WritePhysicalAddress(PVOID address, PVOID buffer, SIZE_T size, SIZE_T* BytesTransferred)
{
  if (!address)
  {
    return STATUS_UNSUCCESSFUL;
  }

  PHYSICAL_ADDRESS Write = { 0 };
  Write.QuadPart = (LONG64)address;
    
    // 將物理空間映射為虛擬空間
  PVOID map = MmMapIoSpace(Write, size, (MEMORY_CACHING_TYPE)PAGE_READWRITE);

  if (!map)
  {
    return STATUS_UNSUCCESSFUL;
  }

    // 開始拷貝數(shù)據(jù)
  RtlCopyMemory(map, buffer, size);
  *BytesTransferred = size;
  MmUnmapIoSpace(map, size);
  return STATUS_SUCCESS;
}

// 從用戶層虛擬地址切換到物理頁地址的函數(shù)
// 將 CR3 寄存器的末尾4個(gè)比特清零,這些比特是用于對齊的,不需要考慮
/*
    參數(shù) cr3:物理地址。
    參數(shù) VirtualAddress:虛擬地址。
*/
ULONG64 TransformationCR3(ULONG64 cr3, ULONG64 VirtualAddress)
{
  cr3 &= ~0xf;
  // 獲取頁面偏移量
  ULONG64 PAGE_OFFSET = VirtualAddress & ~(~0ul << 12);

  // 讀取虛擬地址所在的三級(jí)頁表項(xiàng)
  SIZE_T BytesTransferred = 0;
  ULONG64 a = 0, b = 0, c = 0;

  ReadPhysicalAddress((PVOID)(cr3 + 8 * ((VirtualAddress >> 39) & (0x1ffll))), &a, sizeof(a), &BytesTransferred);

  // 如果 P(存在位)為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~a & 1)
  {
    return 0;
  }

  // 讀取虛擬地址所在的二級(jí)頁表項(xiàng)
  ReadPhysicalAddress((PVOID)((a & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 30) & (0x1ffll))), &b, sizeof(b), &BytesTransferred);

  // 如果 P 為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~b & 1)
  {
    return 0;
  }

  // 如果 PS(頁面大?。?,表示該頁表項(xiàng)映射的是1GB的物理內(nèi)存,直接計(jì)算出物理地址并返回
  if (b & 0x80)
  {
    return (b & (~0ull << 42 >> 12)) + (VirtualAddress & ~(~0ull << 30));
  }

  // 讀取虛擬地址所在的一級(jí)頁表項(xiàng)
  ReadPhysicalAddress((PVOID)((b & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 21) & (0x1ffll))), &c, sizeof(c), &BytesTransferred);

  // 如果 P 為0,表示該頁表項(xiàng)沒有映射物理內(nèi)存,返回0
  if (~c & 1)
  {
    return 0;
  }
  // 如果 PS 為1,表示該頁表項(xiàng)映射的是2MB的物理內(nèi)存,直接計(jì)算出物理地址并返回
  if (c & 0x80)
  {
    return (c & ((~0xfull << 8) & 0xfffffffffull)) + (VirtualAddress & ~(~0ull << 21));
  }
  // 讀取虛擬地址所在的零級(jí)頁表項(xiàng),計(jì)算出物理地址并返回
  ULONG64 address = 0;
  ReadPhysicalAddress((PVOID)((c & ((~0xfull << 8) & 0xfffffffffull)) + 8 * ((VirtualAddress >> 12) & (0x1ffll))), &address, sizeof(address), &BytesTransferred);
  address &= ((~0xfull << 8) & 0xfffffffffull);
  if (!address)
  {
    return 0;
  }

  return address + PAGE_OFFSET;
}

有了如上封裝,那么我們就可以實(shí)現(xiàn)驅(qū)動(dòng)讀寫了,首先我們實(shí)現(xiàn)驅(qū)動(dòng)讀取功能,如下這段代碼是Windows驅(qū)動(dòng)程序的入口函數(shù)DriverEntry,主要功能是讀取指定進(jìn)程的虛擬地址空間中指定地址處的4個(gè)字節(jié)數(shù)據(jù)。

代碼首先通過 PsLookupProcessByProcessId 函數(shù)獲取指定進(jìn)程的 EPROCESS 結(jié)構(gòu)體指針。然后獲取該進(jìn)程的 CR3值,用于將虛擬地址轉(zhuǎn)換為物理地址。接下來,循環(huán)讀取指定地址處的 4 個(gè)字節(jié)數(shù)據(jù),每次讀取 PAGE_SIZE 大小的物理內(nèi)存數(shù)據(jù)。最后輸出讀取到的數(shù)據(jù),并關(guān)閉對 EPROCESS 結(jié)構(gòu)體指針的引用。

需要注意的是,該代碼并沒有進(jìn)行有效性檢查,如沒有檢查讀取的地址是否合法、讀取的數(shù)據(jù)是否在用戶空間,因此存在潛在的風(fēng)險(xiǎn)。另外,該代碼也沒有考慮內(nèi)核模式下訪問用戶空間數(shù)據(jù)的問題,因此也需要進(jìn)行進(jìn)一步的檢查和處理。

// 驅(qū)動(dòng)卸載例程
extern "C" VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
  UNREFERENCED_PARAMETER(pDriver);
  DbgPrint("Uninstall Driver \n");
}

// 驅(qū)動(dòng)入口地址
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING path)
{
  DbgPrint("Hello LyShark \n");

  // 通過進(jìn)程ID獲取eprocess
  PEPROCESS pEProcess = NULL;
  NTSTATUS Status = PsLookupProcessByProcessId((HANDLE)4116, &pEProcess);

  if (NT_SUCCESS(Status) && pEProcess != NULL)
  {

    ULONG64 TargetAddress = 0x401000;
    SIZE_T TargetSize = 4;
    SIZE_T read = 0;

    // 分配讀取空間
    BYTE* ReadBuffer = (BYTE *)ExAllocatePool(NonPagedPool, 1024);

    // 獲取CR3用于轉(zhuǎn)換
    PUCHAR Var = reinterpret_cast<PUCHAR>(pEProcess);
    ULONG64 CR3 = *(ULONG64*)(Var + bit64);
    if (!CR3)
    {
      CR3 = *(ULONG64*)(Var + GetDirectoryTableOffset);
    }

    DbgPrint("[CR3] 寄存器地址 = 0x%p \n", CR3);

    while (TargetSize)
    {
      // 開始循環(huán)切換到CR3
      ULONG64 PhysicalAddress = TransformationCR3(CR3, TargetAddress + read);
      if (!PhysicalAddress)
      {
        break;
      }

      // 讀取物理內(nèi)存
      ULONG64 ReadSize = min(PAGE_SIZE - (PhysicalAddress & 0xfff), TargetSize);
      SIZE_T BytesTransferred = 0;

      // reinterpret_cast 強(qiáng)制轉(zhuǎn)為PVOID類型
      Status = ReadPhysicalAddress(reinterpret_cast<PVOID>(PhysicalAddress), reinterpret_cast<PVOID>((PVOID *)ReadBuffer + read), ReadSize, &BytesTransferred);
      TargetSize -= BytesTransferred;
      read += BytesTransferred;

      if (!NT_SUCCESS(Status))
      {
        break;
      }

      if (!BytesTransferred)
      {
        break;
      }
    }

    // 關(guān)閉引用
    ObDereferenceObject(pEProcess);

    // 輸出讀取字節(jié)
    for (size_t i = 0; i < 4; i++)
    {
      DbgPrint("[讀入字節(jié) [%d] ] => 0x%02X \n", i, ReadBuffer[i]);
    }
  }

  // 關(guān)閉引用
  UNREFERENCED_PARAMETER(path);

  // 卸載驅(qū)動(dòng)
  pDriver->DriverUnload = DriverUnload;
  return STATUS_SUCCESS;
}

編譯并運(yùn)行上述代碼片段,則會(huì)讀取進(jìn)程ID為41160x401000處的地址數(shù)據(jù),并以字節(jié)的方式輸出前四位,輸出效果圖如下所示;

驅(qū)動(dòng)開發(fā):內(nèi)核物理內(nèi)存尋址讀寫

寫出數(shù)據(jù)與讀取數(shù)據(jù)基本一致,只是調(diào)用方法從ReadPhysicalAddress變?yōu)榱?code>WritePhysicalAddress其他的照舊,但需要注意的是讀者再使用寫出時(shí)需要自行填充一段堆用于存儲(chǔ)需要寫出的字節(jié)集。

// 驅(qū)動(dòng)卸載例程
extern "C" VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
  UNREFERENCED_PARAMETER(pDriver);
  DbgPrint("Uninstall Driver \n");
}

// 驅(qū)動(dòng)入口地址
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING path)
{
  DbgPrint("Hello LyShark \n");

  // 物理頁寫
  PEPROCESS pEProcess = NULL;
  NTSTATUS Status = PsLookupProcessByProcessId((HANDLE)4116, &pEProcess);

  // 判斷pEProcess是否有效
  if (NT_SUCCESS(Status) && pEProcess != NULL)
  {
    ULONG64 TargetAddress = 0x401000;
    SIZE_T TargetSize = 4;
    SIZE_T read = 0;

    // 申請空間并填充寫出字節(jié)0x90
    BYTE* ReadBuffer = (BYTE *)ExAllocatePool(NonPagedPool, 1024);

    for (size_t i = 0; i < 4; i++)
    {
      ReadBuffer[i] = 0x90;
    }

    // 獲取CR3用于轉(zhuǎn)換
    PUCHAR Var = reinterpret_cast<PUCHAR>(pEProcess);
    ULONG64 CR3 = *(ULONG64*)(Var + bit64);
    if (!CR3)
    {
      CR3 = *(ULONG64*)(Var + GetDirectoryTableOffset);
      // DbgPrint("[CR3] 寄存器地址 = 0x%p \n", CR3);
    }

    while (TargetSize)
    {
      // 開始循環(huán)切換到CR3
      ULONG64 PhysicalAddress = TransformationCR3(CR3, TargetAddress + read);
      if (!PhysicalAddress)
      {
        break;
      }

      // 寫入物理內(nèi)存
      ULONG64 WriteSize = min(PAGE_SIZE - (PhysicalAddress & 0xfff), TargetSize);
      SIZE_T BytesTransferred = 0;
      Status = WritePhysicalAddress(reinterpret_cast<PVOID>(PhysicalAddress), reinterpret_cast<PVOID>(ReadBuffer + read), WriteSize, &BytesTransferred);
      TargetSize -= BytesTransferred;
      read += BytesTransferred;

      // DbgPrint("[寫出數(shù)據(jù)] => %d | %0x02X \n", WriteSize, ReadBuffer + read);
      if (!NT_SUCCESS(Status))
      {
        break;
      }

      if (!BytesTransferred)
      {
        break;
      }
    }

    // 關(guān)閉引用
    ObDereferenceObject(pEProcess);
  }

  // 關(guān)閉引用
  UNREFERENCED_PARAMETER(path);

  // 卸載驅(qū)動(dòng)
  pDriver->DriverUnload = DriverUnload;
  return STATUS_SUCCESS;
}

如上代碼運(yùn)行后,會(huì)向進(jìn)程ID為41160x401000處寫出4字節(jié)的0x90機(jī)器碼,讀者可通過第三方工具驗(yàn)證內(nèi)存,輸出效果如下所示;

驅(qū)動(dòng)開發(fā):內(nèi)核物理內(nèi)存尋址讀寫文章來源地址http://www.zghlxwxcb.cn/news/detail-500498.html

到了這里,關(guān)于驅(qū)動(dòng)開發(fā):內(nèi)核物理內(nèi)存尋址讀寫的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 驅(qū)動(dòng)開發(fā):內(nèi)核文件讀寫系列函數(shù)

    驅(qū)動(dòng)開發(fā):內(nèi)核文件讀寫系列函數(shù)

    在應(yīng)用層下的文件操作只需要調(diào)用微軟應(yīng)用層下的 API 函數(shù)及 C庫 標(biāo)準(zhǔn)函數(shù)即可,而如果在內(nèi)核中讀寫文件則應(yīng)用層的API顯然是無法被使用的,內(nèi)核層需要使用內(nèi)核專有API,某些應(yīng)用層下的API只需要增加Zw開頭即可在內(nèi)核中使用,例如本章要講解的文件與目錄操作相關(guān)函數(shù),多

    2024年02月08日
    瀏覽(23)
  • 【Linux驅(qū)動(dòng)開發(fā)】004 物理內(nèi)存與虛擬內(nèi)存的轉(zhuǎn)換

    【Linux驅(qū)動(dòng)開發(fā)】004 物理內(nèi)存與虛擬內(nèi)存的轉(zhuǎn)換

    MMU 全稱叫做 Memory?Manage Unit,也就是 內(nèi)存管理單元。 在老版本的 Linux 中要求處理器必須有 MMU,但是現(xiàn)在Linux 內(nèi)核已經(jīng)支持無 MMU 的處理器了。MMU主要功能: ①、完成虛擬空間到物理空間的映射。? ②、內(nèi)存保護(hù),設(shè)置存儲(chǔ)器的訪問權(quán)限,設(shè)置虛擬存儲(chǔ)空間的緩沖特性。?

    2024年02月05日
    瀏覽(20)
  • 驅(qū)動(dòng)開發(fā):內(nèi)核解析內(nèi)存四級(jí)頁表

    驅(qū)動(dòng)開發(fā):內(nèi)核解析內(nèi)存四級(jí)頁表

    當(dāng)今操作系統(tǒng)普遍采用64位架構(gòu),CPU最大尋址能力雖然達(dá)到了64位,但其實(shí)僅僅只是用到了48位進(jìn)行尋址,其內(nèi)存管理采用了 9-9-9-9-12 的分頁模式, 9-9-9-9-12 分頁表示物理地址擁有四級(jí)頁表,微軟將這四級(jí)依次命名為PXE、PPE、PDE、PTE這四項(xiàng)。 關(guān)于內(nèi)存管理和分頁模式,不同的操

    2024年02月06日
    瀏覽(24)
  • Linux 內(nèi)核學(xué)習(xí) 3 - 虛擬內(nèi)存和物理內(nèi)存

    Linux 內(nèi)核學(xué)習(xí) 3 - 虛擬內(nèi)存和物理內(nèi)存

    虛擬內(nèi)存其實(shí)是 CPU 和操作系統(tǒng)使用的一個(gè)障眼法,聯(lián)手給進(jìn)程編織了一個(gè)假象,讓進(jìn)程誤以為自己獨(dú)占了全部的內(nèi)存空間 : 在 32 位系統(tǒng)中,進(jìn)程以為自己獨(dú)占了 3G 的內(nèi)存空間。 在 64 位系統(tǒng)中,進(jìn)程以為自己獨(dú)占了 128T 的內(nèi)存空間。 這么做的好處是,操作系統(tǒng)為每個(gè)進(jìn)程

    2024年01月21日
    瀏覽(31)
  • 【Linux 內(nèi)核源碼分析】物理內(nèi)存組織結(jié)構(gòu)

    多處理器系統(tǒng)兩種體系結(jié)構(gòu): 非一致內(nèi)存訪問(Non-Uniform Memory Access,NUMA):這種體系結(jié)構(gòu)下,內(nèi)存被劃分成多個(gè)內(nèi)存節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)由不同的處理器訪問。訪問一個(gè)內(nèi)存節(jié)點(diǎn)所需的時(shí)間取決于處理器和內(nèi)存節(jié)點(diǎn)之間的距離,因此處理器與內(nèi)存節(jié)點(diǎn)之間的距離會(huì)影響內(nèi)存訪問

    2024年02月22日
    瀏覽(22)
  • 物理尋址和功能尋址,服務(wù)器不同的應(yīng)答策略和NRC回復(fù)策略

    物理尋址和功能尋址,服務(wù)器不同的應(yīng)答策略和NRC回復(fù)策略

    詳細(xì)策略上,又分為服務(wù)有子功能,和不存在子功能。 存在子功能的情況下,又分為supress postive response (即子功能字節(jié)的bit7)位=1,和=0兩種情況 iso 14229-1也給我們列出了表格 1.1.1先講功能尋址,supress postive response =0的情況! 看圖之前,對圖中描述作出必要的解釋 *1)Yes代

    2024年04月28日
    瀏覽(55)
  • 字符設(shè)備驅(qū)動(dòng)(內(nèi)核態(tài)用戶態(tài)內(nèi)存交互)

    字符設(shè)備驅(qū)動(dòng)(內(nèi)核態(tài)用戶態(tài)內(nèi)存交互)

    內(nèi)核驅(qū)動(dòng):運(yùn)行在內(nèi)核態(tài)的動(dòng)態(tài)模塊,遵循內(nèi)核模塊框架接口,更傾向于插件。 應(yīng)用程序:運(yùn)行在用戶態(tài)的進(jìn)程。 應(yīng)用程序與內(nèi)核驅(qū)動(dòng)交互通過既定接口,內(nèi)核態(tài)和用戶態(tài)訪問依然遵循內(nèi)核既定接口。 系統(tǒng):openEuler-20.03-LTS-SP3 char_module.c Makefile 驅(qū)動(dòng)構(gòu)建 驅(qū)動(dòng)信息確認(rèn) 應(yīng)用程

    2024年02月11日
    瀏覽(26)
  • 【嵌入式環(huán)境下linux內(nèi)核及驅(qū)動(dòng)學(xué)習(xí)筆記-(10-內(nèi)核內(nèi)存管理)】

    【嵌入式環(huán)境下linux內(nèi)核及驅(qū)動(dòng)學(xué)習(xí)筆記-(10-內(nèi)核內(nèi)存管理)】

    對于包含MMU(內(nèi)存管理單元)的處理器而言,linux系統(tǒng)以虛擬內(nèi)存的方式為每個(gè)進(jìn)程分配最大4GB的內(nèi)存。這真的4GB的內(nèi)存空間被分為兩個(gè)部分–用戶空間 與 內(nèi)核空間。用戶空間地地址分布為0~3GB,剩下的3 ~ 4GB 為內(nèi)核空間。如下圖。 用戶進(jìn)程通常只能訪問用戶空間的虛擬地址

    2024年02月11日
    瀏覽(23)
  • linux|操作系統(tǒng)|centos7物理機(jī)安裝網(wǎng)卡驅(qū)動(dòng)8188gu(內(nèi)核升級(jí),firmware固件,USB設(shè)備管理,module管理)

    linux|操作系統(tǒng)|centos7物理機(jī)安裝網(wǎng)卡驅(qū)動(dòng)8188gu(內(nèi)核升級(jí),firmware固件,USB設(shè)備管理,module管理)

    目前服務(wù)器領(lǐng)域centos7基本是主流的操作系統(tǒng),而linux相對于Windows來說,軟硬件方面的支持是差很多的,在硬件方面來說,以一個(gè)免驅(qū)的網(wǎng)卡為例,window xp可能不會(huì)自動(dòng)識(shí)別到,但Windows10基本都會(huì)自動(dòng)識(shí)別到,簡簡單單的即插即用。根本原因在Windows隨著版本的升級(jí),內(nèi)置的各

    2024年01月20日
    瀏覽(37)
  • linux驅(qū)動(dòng)開發(fā)--day1(驅(qū)動(dòng)、內(nèi)核模塊及相關(guān)命令、內(nèi)核模塊傳參)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包