內核知識第六講,內核編寫規范,以及獲取GDT表


          內核知識第六講,內核編寫規范,以及獲取GDT表

一丶內核驅動編寫規范

 我們都知道,在ring3下,如果我們的程序出錯了.那么就崩潰了.但是在ring0下,只要我們的程序崩潰了.那么直接就藍屏了.

那么有那些規范?

    1.最基本的檢查要有. 比如檢查指針是否為NULL,基本的校驗錯誤必須有

    2.對內存進行操作的時候,要進行內存判斷.下面提供內存判斷的API

    

BOOLEAN 
  MmIsAddressValid(
    IN PVOID  VirtualAddress
    );

給定一個緩沖區,然后檢查其內存是否有效

  

VOID 
  ProbeForWrite(
    IN CONST VOID  *Address,
    IN SIZE_T  Length,
    IN ULONG  Alignment
    );

給定一個緩沖區.然后檢查是否可以寫. 但是注意,檢測的是ring3下的內存地址.

     3.盡量不要使用太大變量,因為在內核中.內存地址都是共享的.如果你使用了很大.那么相應的內核空間就會變少.

   比如不能這樣寫  char szBuf[0x1000];這樣是使用棧內存了.但是編譯是不通過了.操作系統不讓你這樣使用.

    但是你可以寫成 char szBuf1[0x500], char szBuf2[0x500]; 但是沒有任何意義.

    4.ring0下不能直接訪問ring3的內存

    這個是有原因的.因為ring0知道一塊物理內存.但是不知道是那個進程的.所以不能直接訪問.

二丶分頁內存與非分頁內存管理

我們在內核下申請空間的API:

  

PVOID 
  ExAllocatePool(
    IN POOL_TYPE  PoolType,    //指定內存的類型
    IN SIZE_T  NumberOfBytes    //申請的字節數
    );

但是第一個參數是我們制定內存的內容是一個結構體

typedef enum _POOL_TYPE {
  NonPagedPool,      //非分頁管理
  PagedPool,        //分頁管理
  NonPagedPoolMustSucceed,
  DontUseThisType,
  NonPagedPoolCacheAligned,
  PagedPoolCacheAligned,
  NonPagedPoolCacheAlignedMustS
} POOL_TYPE;

然后類型中有個非分頁管理以及分頁管理,什么意思?

意思就是在內核中申請一塊內存,這塊內存可否與磁盤交互. 

非分頁內存:  不可以進行交互.申請了這塊內存就不能動了.

分頁內存:      可以進行交互.當內存資源緊張的是否,而這塊內存很少是否.可以暫時放到磁盤.

操作系統的代碼都是放到非分頁內存中的.

 

三丶設置分頁內存

了解了分頁內存和非分頁內存.那么此時就產生了一個新的問題.

我們的代碼.有的只調用一次,不該占着這個空間不放.那么我們就要設置為分頁內存中.

關鍵字:

  總共兩種方式:

   

1.#pragma code_seg("PAGE")  //每個函數都加上,設置到PAGE節中

例如:

  

但是這種方式,很麻煩,且每寫一個函數都要設置.那么此時就有第二種方式

 

2.#pragma Alloc_text("PAGE",函數名,.....) //類似於一個數組一樣,可以設置多個.

  但是此時就要注意了.我們就需要一個頭文件了.把我們的函數聲明都放到頭文件中.

  然后下方設置.

Page節,和INIT節. 內核中,我們編寫的sys驅動程序,其實也是一個PE文件.  類似於我們的ring3下的DLL, ring3的DLL是給應用程序使用的.而sys則是給操作系統使用的. 只不過一個是3環一個是0環

Page節: 這個節則是我們說的分頁內存節. 我們給了函數指針.那么就代表這塊內存很自由了.操作系統可以在資源緊張的時候使用.

INIT節:  這個節則是初始化的節.例如我們的入口函數,只用一次初始化而已,不用占着內存.所以給INIT節中.那么操作系統會初始化之后釋放這塊內存.這樣可以留給其它驅動使用.

 

 四丶設置內核代碼運行的CPU在那個核心上跑.並獲取出來每個核心的GDT表.

代碼:

  

int shift = 1;
char szGDT[6];
nCount = KeQueryActiveProcessors();//獲取CUP核心個數,按位來算.
while(shift != 0x80000000)
  {
    if (nCount & shift)
    {
      KeSetSystemAffinityThread(nCount & shift);//設置在那個線程跑
      __asm
      {
        sgdt szGDT
      }
      KdPrint(("limit:%p  GDT:%p\n", *(short*)szGDT, *(int*)(szGDT + 2)));
    }

    shift <<= 1;
  }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM