欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
驅動(dòng)程序中文件,定時(shí)器,IO

內容要點(diǎn)展示:

內核中文件的使用

內核定時(shí)器的使用

IO_WORKITEM 的使用

文章概要

最近一個(gè)項目呢,是做一個(gè)基于 TDI 的防火墻,

而在該防火墻的實(shí)現過(guò)程中呢,有對文件的處理,

因為這個(gè)防火墻中涉及到日志文件,黑名單文件,白名單文件的處理,

所以整個(gè)的 TDI 防火墻中對于文件處理這一塊,

就涉及到文件的創(chuàng )建,打開(kāi),讀取,寫(xiě)入等等文件操作。

而在內核中處理文件呢,自然有其特殊的一面,所以不太好操作。

同時(shí)還需要有定時(shí)器的處理以及 IRQL 的控制等細節。

文件操作概要

Windows 操作系統的內核環(huán)境中,對于文件的路徑和在應用層中的表示是不同的,

在應用層中,我們對于文件的路徑很簡(jiǎn)單,比如:E:\Driver\CodeProject\Sample.txt

但是在內核環(huán)境下,則必須在前面的路徑中再加上一點(diǎn)點(diǎn):\DosDevices\E:\Driver\CodeProject\Sample.txt 。

其實(shí)這一點(diǎn)呢,估計寫(xiě)過(guò)一點(diǎn)點(diǎn)驅動(dòng)程序的都很熟悉了,因為創(chuàng )建符號鏈接名的時(shí)候都是這樣來(lái)實(shí)現的,

還有值得一提的是,在 Windows 2000 以及以后的 Windows 操作系統中,可以通過(guò) ?? 來(lái)代替 DosDevices 了,

也就是說(shuō)內核中文件的路徑又可以寫(xiě)成:\??\E:\Driver\CodeProject\Sample.txt 。

然后呢,既然有了文件的路徑,那么同樣可以通過(guò) 內核  API(不是 Win32  API) 來(lái)打開(kāi)文件從而獲得句柄。

獲得句柄以后呢,就可以通過(guò) 內核  API  來(lái)完成讀寫(xiě)等等操作了。

文件操作涉及的內核 API

首先,來(lái)看一下將要使用的針對于文件處理的 內核 API 。

對于上面的這些 API 呢,MSND 上明確記載:

must be running at IRQL = PASSIVE_LEVEL and with APCs enabled.

也就是說(shuō),它們必須運行在 IRQL PASSIVE_LEVEL 層,

眾所周知的是,PASSIVE_LEVEL 是所有中斷請求級別 (IRQL) 中最低的,

也就是說(shuō),工作在這個(gè)中斷請求級別下的任務(wù)相比于工作在其他 IRQL 層(比如 DISPATCH_LEVEL)的任務(wù)來(lái)說(shuō),

它們獲得 CPU 處理的時(shí)間會(huì )更少,至于為什么對于文件的處理的時(shí)候 IRQL 必須為最低呢,

這里其實(shí)稍動(dòng)腦子想想就能夠明白,對于文件的處理向來(lái)都是很慢的,需要消耗很多的 CPU 時(shí)間,

如果你在內核中進(jìn)行文件操作,而且這些操作不是工作在 PASSIVE_LEVEL 層的話(huà),

那么這些文件操作就有更多的機會(huì )獲取到 CPU 時(shí)間,

從而會(huì )消耗很多的 CPU 時(shí)間,從而造成系統性能的大幅度下降。                 

然后的話(huà),上面的這些 API 如果你不是在 PASSIVE_LEVEL 下調用的話(huà),

那么 Windows 會(huì )很坦率的給你一個(gè)藍屏,從而很顯示的提示您:非法了。         

再來(lái)看看這些 API 的原型,至于這些 API 的具體信息,MSDN 中有很完整的解釋?zhuān)@里就不給出了:

NTSTATUS  
ZwCreateFile(
             OUT PHANDLE  FileHandle,
             IN ACCESS_MASK  DesiredAccess,
             IN POBJECT_ATTRIBUTES  ObjectAttributes,
             OUT PIO_STATUS_BLOCK  IoStatusBlock,
             IN PLARGE_INTEGER  AllocationSize  OPTIONAL,
             IN ULONG  FileAttributes,
             IN ULONG  ShareAccess,
             IN ULONG  CreateDisposition,
             IN ULONG  CreateOptions,
             IN PVOID  EaBuffer  OPTIONAL,
             IN ULONG  EaLength
             );
NTSTATUS
ZwOpenFile(
           OUT PHANDLE  FileHandle,
           IN ACCESS_MASK  DesiredAccess,
           IN POBJECT_ATTRIBUTES  ObjectAttributes,
           OUT PIO_STATUS_BLOCK  IoStatusBlock,
           IN ULONG  ShareAccess,
           IN ULONG  OpenOptions
           );
NTSTATUS 
ZwClose(
        IN HANDLE  Handle
        );

        

NTSTATUS 
ZwReadFile(
           IN HANDLE  FileHandle,
           IN HANDLE  Event  OPTIONAL,
           IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
           IN PVOID  ApcContext  OPTIONAL,
           OUT PIO_STATUS_BLOCK  IoStatusBlock,
           OUT PVOID  Buffer,
           IN ULONG  Length,
           IN PLARGE_INTEGER  ByteOffset  OPTIONAL,
           IN PULONG  Key  OPTIONAL
           );
NTSTATUS 
ZwWriteFile(
            IN HANDLE  FileHandle,
            IN HANDLE  Event  OPTIONAL,
            IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
            IN PVOID  ApcContext  OPTIONAL,
            OUT PIO_STATUS_BLOCK  IoStatusBlock,
            IN PVOID  Buffer,
            IN ULONG  Length,
            IN PLARGE_INTEGER  ByteOffset  OPTIONAL,
            IN PULONG  Key  OPTIONAL
            );
           
NTSTATUS 
ZwQueryInformationFile(
                       IN HANDLE  FileHandle,
                       OUT PIO_STATUS_BLOCK  IoStatusBlock,
                       OUT PVOID  FileInformation,
                       IN ULONG  Length,
                       IN FILE_INFORMATION_CLASS  FileInformationClass
                       );

定時(shí)器涉及的內核 API

在內核中使用定時(shí)器呢,有好幾種方式,

我這里只介紹了我在這個(gè) TDI 防火墻項目中所使用的定時(shí)器,

至于其他幾種定時(shí)器的使用呢,我給出幾篇來(lái)自博客園和看雪的博文的鏈接,

這幾篇博文對定時(shí)器的介紹都是非常貼切詳細的,有想了解定時(shí)器的這里榮老衲推薦一下。

定時(shí)器:http://www.cnblogs.com/mydomain/archive/2010/11/14/1877125.html

高手進(jìn)階windows內核定時(shí)器之一:http://bbs.pediy.com/showthread.php?t=60474

高手進(jìn)階windows內核定時(shí)器之二:http://bbs.pediy.com/showthread.php?t=60579

VOID 
KeInitializeTimer(
                  IN PKTIMER  Timer
                  );
              
VOID 
KeInitializeDpc(
                IN PRKDPC  Dpc,
                IN PKDEFERRED_ROUTINE  DeferredRoutine,
                IN PVOID  DeferredContext
                );
BOOLEAN 
KeSetTimer(
           IN PKTIMER  Timer,
           IN LARGE_INTEGER  DueTime,
           IN PKDPC  Dpc  OPTIONAL
           );

// DPC 回調函數

VOID
CustomDpc(
          IN struct _KDPC  *Dpc,
          IN PVOID  DeferredContext,
          IN PVOID  SystemArgument1,
          IN PVOID  SystemArgument2
          );

對于上面這些 API 的使用呢,就是先調用 KeInitializeTimer 來(lái)初始化一個(gè)內核定時(shí)器,

然后調用 KeInitializeDpc 來(lái)初始化一個(gè) DPC ,在該 DPC 中需要指定回調函數 CustomDpc ,

然后再調用 KeSetTimer 來(lái)將定時(shí)器和 DPC  關(guān)聯(lián)起來(lái),同時(shí)也在這個(gè) API 中指定定時(shí)器觸發(fā)的時(shí)間間隔。

需要注意的是,使用 KeSetTimer 設置好定時(shí)器后,定時(shí)器只會(huì )觸發(fā)一次,

如果要持續的觸發(fā)定時(shí)器,則必須在 CustomDpc 這個(gè)回調函數中重新調用 KeSetTimer 來(lái)重新設置定時(shí)器觸發(fā)。

還有需要注意的一點(diǎn)是在 CustomDpc 這個(gè)回調函數其是工作在 DISPATCH_LEVEL 這個(gè) IRQL 層而非 PASSIVE_LEVEL 。

IO_WORKITEM 概要

對于這個(gè) TDI 防火墻項目呢,我要實(shí)現的是如下這種方式的文件處理操作,

1. 每隔 10s 即需要重新讀取黑名單和白名單中的 IP 地址。

2. 每隔 1h 即需要重新創(chuàng )建日志文件。

所以,我的思路就是通過(guò)兩個(gè)內核定時(shí)器來(lái)實(shí)現,

然后在內核定時(shí)器中來(lái)處理上面的這兩個(gè)針對文件的操作,

但是上面也提到了,在定時(shí)器所綁定的 DPC 的回調函數 CustomDpc 是工作在 DISPATCH_LEVEL 下,

而我們的 ZwCreateFile 之類(lèi)的函數均必須工作在 PASSIVE_LEVEL 下,

如果是直接在 CustomDpc 下直接進(jìn)行 ZwCreateFile 這些函數的話(huà),

乖乖,直接給個(gè)很耀眼的提示 - 藍屏。

要解決上面的這個(gè)問(wèn)題呢,就必須要用到 IO_WORKITEM,

因為 IO_WORKITEM 這個(gè)東西呢,與其綁定的回調函數是工作在 PASSIVE_LEVEL 下的,

IO_WORKITEM 其實(shí)就是一個(gè) IO 工作項,在操作系統中,由系統自行維護了一個(gè) IO_WORKITEM 隊列,

而每一個(gè) IO_WORKITEM 呢均有其對應的一個(gè)回調函數,眾所周知的是,

操作系統有一個(gè)系統線(xiàn)程池,所以系統會(huì )自動(dòng)的使用這個(gè)系統線(xiàn)程池中的某一個(gè)空閑線(xiàn)程,

然后這個(gè)空閑線(xiàn)程從 IO_WORKITEM 隊列中取出一個(gè) IO_WORKITEM ,

然后這個(gè)線(xiàn)程便調用這個(gè) IO_WORKITEM 的回調函數進(jìn)行處理,

這樣這個(gè) IO_WORKITEM 也就得到了處理,關(guān)鍵是它的處理還是在 IRQL PASSIVE_LEVEL 時(shí)進(jìn)行的。

而這剛好適應了我前面的需求。

IO_WORKITEM 涉及的內核 API

只列出我所使用的,關(guān)于其他的可以查看 MSDN

PIO_WORKITEM
IoAllocateWorkItem(
                   IN PDEVICE_OBJECT  DeviceObject
                   );
VOID
IoQueueWorkItem(
                IN PIO_WORKITEM  IoWorkItem,
                IN PIO_WORKITEM_ROUTINE  WorkerRoutine,
                IN WORK_QUEUE_TYPE  QueueType,
                IN PVOID  Context
                );

// IO_WORKITEM 回調函數   

VOID
WorkItem (
          IN PDEVICE_OBJECT  DeviceObject,
          IN PVOID  Context 
          );

不完整代碼展示:

基本定義:

 
//定義讀取黑白文件的時(shí)間間隔為 10 秒
#define READ_FILE_INTERVAL    -10000 * 1000 * 10
//定義創(chuàng  )建新的日志文件間隔為 1 小時(shí)
#define CREATE_LOGFILE_INTERVAL -10000 * 1000 * 60 * 60
 
HANDLE            hBlackFile; 
typedef struct _KTIMER_EXT 
{    
    KDPC                kDpc;                //存儲 DPC 對象
    KTIMER                kTimer;                //存儲計時(shí)器對象
    LARGE_INTEGER        dueInterval;        //記錄計時(shí)器間隔時(shí)間 
 
} KTIMER_EXT, * PKTIMER_EXT;
 
 
//兩個(gè)內核定時(shí)器
KTIMER_EXT queryFileInfoKTimerExt;
KTIMER_EXT createLogKTimerExt;
 
 
//保存設備句柄
PDEVICE_OBJECT        pDeviceObj;
 
//從黑名單文件中讀取出所有的黑名單記錄
VOID ReadBlackFile();
 
//查詢(xún)文件信息的 Work Item 的回調處理函數
VOID WorkerItemQueryFileInfoRoutine(PDEVICE_OBJECT  DeviceObject, PVOID  Context);
 
//查詢(xún)文件信息定時(shí)器的 DPC 回調函數
VOID QueryFileInfoTimerDpcRoutine(PKDPC pDpc, PVOID pContext, PVOID SysArg1, PVOID SysArg2);
               

打開(kāi)或者創(chuàng )建文件:

    WCHAR fileName2[] = L"\\??\\C:\\NdisBlack.txt";
    WCHAR fileName3[] = L"\\??\\C:\\NdisWhite.txt";
    NTSTATUS status;
 
    UNICODE_STRING unifilename2;
    UNICODE_STRING unifilename3;
 
    OBJECT_ATTRIBUTES oa;
 
    IO_STATUS_BLOCK iostatus;
 
    RtlInitUnicodeString(&unifilename2,fileName2);
    RtlInitUnicodeString(&unifilename3,fileName3);

                  

    InitializeObjectAttributes(&oa,&unifilename1, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL,NULL);
    status = ZwCreateFile(&hBlackFile, FILE_READ_DATA|FILE_READ_ATTRIBUTES , &oa, &iostatus, NULL,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0, 0);
    if(!NT_SUCCESS(status))
    {
        DbgPrint("ZwCreateFile(BlackFile) Failed %8x",status);
        return status;
    }

            

讀取文件:

    ULONG length;
    PCHAR pBuffer;
    NTSTATUS status;
    LARGE_INTEGER offset = {0};
    IO_STATUS_BLOCK ioStatus;
 
    pBuffer = (PCHAR)ExAllocatePool(NonPagedPool, ROWLENGTH);
 
    while(1)
    {
        RtlZeroMemory(pBuffer, ROWLENGTH);
 
        status = ZwReadFile(hBlackFile, NULL, NULL, NULL, &ioStatus, pBuffer, ROWLENGTH, &offset, NULL);
        if(!NT_SUCCESS(status))
        {
            if(STATUS_END_OF_FILE == status)
            {
                DbgPrint("Read All File Contents ! \n"); 
                break;
            }
        }
 
        DbgPrint("Current    ID: %d \n",lTotalBlackRecordCount);
        DbgPrint("Current Data: %s \n",chArrayBlack[lTotalBlackRecordCount]);
 
        //包括一個(gè) ; 以及每一行的結束符 \t\r 所以總共是 3 個(gè)字符
        length = i + 3;
        offset.QuadPart += length;
    }

寫(xiě)入文件:

    NTSTATUS            ntstatus;
    IO_STATUS_BLOCK        iostatus;
    LARGE_INTEGER        ByteOffset = { 0 } ;
 
    ntstatus = ZwWriteFile(hLogFile, NULL, NULL, NULL, &iostatus, pszDest,pszDestLen, &ByteOffset, NULL);

         

定時(shí)器設置(在其中綁定了 DPC 回調函數):

pDeviceObj = theDriverObject->DeviceObject;
 
queryFileInfoKTimerExt.dueInterval.QuadPart = READ_FILE_INTERVAL;
KeInitializeTimer(&queryFileInfoKTimerExt.kTimer);
KeInitializeDpc(&queryFileInfoKTimerExt.kDpc, QueryFileInfoTimerDpcRoutine, (PVOID)&queryFileInfoKTimerExt);
KeSetTimer(&queryFileInfoKTimerExt.kTimer, queryFileInfoKTimerExt.dueInterval, &queryFileInfoKTimerExt.kDpc);
 
DbgPrint("讀文件定時(shí)器設置成功 ! \n");
 
 

定時(shí)器之 DPC 回調函數(在其中創(chuàng )建了 IO_WORKITEM):

//在該定時(shí)器的回調函數中重新讀取黑白文件
//定時(shí)器處理函數運行在 DISPATCH_LEVEL
VOID QueryFileInfoTimerDpcRoutine(PKDPC pDpc, PVOID pContext, PVOID SysArg1, PVOID SysArg2)
{
    PKTIMER_EXT                    pTmpKTimerExt;
    PIO_WORKITEM                pIoWorkItem;
 
    //由于 ZwQueryInformationFile 必須運行在 PASSIVE_LEVEL 
    //而當前的這個(gè)函數作為內核定時(shí)器的處理函數,其工作在 DISPATCH_LEVEL 
    //所以如果在該函數中直接調用 ZwQueryInformationFile 會(huì )由于 IRQL 的不符合而導致藍屏
    //所以在這里使用一個(gè) IO_WORKITEM 來(lái)解決
    //因為 IO_WORKITEM 的回調函數是在 PASSIVE_LEVEL 中處理的
    //所以可以在 IO_WORKITEM 的回調函數中來(lái)調用 ZwQueryInformationFile 
    pIoWorkItem = IoAllocateWorkItem(pDeviceObj);
    if(pIoWorkItem)
    {
        IoQueueWorkItem(pIoWorkItem, WorkerItemQueryFileInfoRoutine, DelayedWorkQueue, NULL);
    }
 
    //#if DBG
    //    _asm int 3
    //#endif
 
    pTmpKTimerExt = (PKTIMER_EXT)pContext;
 
    KeSetTimer(&pTmpKTimerExt->kTimer, pTmpKTimerExt->dueInterval, &pTmpKTimerExt->kDpc);
 
    DbgPrint("讀文件定時(shí)器再次設置成功 ! \n");
}

IO_WORKITEM 回調函數:

//Work Item 回調函數,用來(lái)查詢(xún)文件屬性信息從而判斷是否需要重新讀入黑白名單
//WorkItem 處理函數運行在 PASSIVE_LEVEL
VOID WorkerItemQueryFileInfoRoutine(PDEVICE_OBJECT  DeviceObject, PVOID  Context )
{    
    NTSTATUS                    status;
    LARGE_INTEGER                localTime;
 
    IO_STATUS_BLOCK                ioStatus;
    FILE_BASIC_INFORMATION        flBscInfo;
 
    //查詢(xún)黑名單文件屬性信息
    status = ZwQueryInformationFile(hBlackFile, &ioStatus, &flBscInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
    if(NT_SUCCESS(status))
    {
        ExSystemTimeToLocalTime(&flBscInfo.ChangeTime, &localTime);
        RtlTimeToTimeFields(&localTime, &timeFields);
 
        if(prevReadBlackTime.QuadPart < localTime.QuadPart)
        {
            DbgPrint("上一次讀取的時(shí)間小于黑名單文件的最新修改時(shí)間,所以需要重新讀取黑名單 \n");
 
            //重新讀取黑名單
            ReadBlackFile();
 
            //重新設置上一次讀取黑名單文件的時(shí)間
            prevReadBlackTime.QuadPart = localTime.QuadPart;
        }
        else
        {
            DbgPrint("不需要重新讀取黑名單 \n");
        }
    }
}

版權所有,迎轉載,但轉載請注明: 轉載自 Zachary.XiaoZhen - 夢(mèng)想的天空

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
驅動(dòng)編程基礎教程第五章:時(shí)間與定時(shí)器 - Aliwy編程空間[http://www.ntd...
深入理解ZwCreateFile
驅動(dòng)讀寫(xiě)超時(shí)處理
干貨 | FreeRTOS 學(xué)習筆記
異步IO、APC、IO完成端口、線(xiàn)程池與高性能服務(wù)器
JRuby 和 Java 7 我們可以期待什么
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久