《Windows內核安全與驅動編程》-第十章-磁盤的過濾學習-day4

10.3.6 bitmap 的作用和分析

​ 在之前我們多次看到了bitmap,但是卻一直不知道它是什麼,它的作用是幹嘛。接下來我們去看,但是具體的bitmap 的實現很複雜,如果沒有特殊興趣的話,可以只看它的接口說明,而不管具體的實現過程。

​ 顧名思義,bitmap就是一個位圖。它實際上是一些內存塊,這些內存塊的每一位用來標識一個磁盤上的最小訪問單位,一般情況下是一個扇區。每一位可以被設置或者清除,用來標識這個扇區的兩種對應狀態。

​ 因爲我們要對磁盤進行還原,所以需要將數據存儲到其他地方。所以bitmap上的每一位對應一個扇區,有多少個扇區就有多少個位。這個位爲0則表示:這個位所對應的扇區的數據沒有被存儲到其他的地方。這個位爲1則表示:這個位對應的扇區的數據被存儲到其他地方了。

​ bitmap的生命週期,爲這次保護系統啓動直到系統重啓。我們在讀寫數據的時候,根據bitmap的位爲0還是1,來判斷從哪裏讀或者寫到哪裏去。而重啓之後,所有的bitmap位都歸零,這時無論什麼操作都不會到轉存處拿數據,也就達到了去保護的功能。

​ 之所以說bitmap是一些內存塊而不是一個連續的內存,是因爲在涉及bitmap的時候考慮到它所表示的位圖可能對應着很大一塊磁盤區域,即使是用1位來表示512字節的數據也有可能是很大的一片內存空間。所以在設計bitmap的時候需要按需分配內存。只有在用到的時候纔去對應分配,這樣就可以達到節約空間的目的。

首先來看bitmap的數據結構。

typedef unsigned char tBitmap;

typedef struct _DP_BITMAP_
{
	//這個卷中的每個扇區有多少字節,這同樣也說明了bitmap中一個位所對應的字節數
    unsigned long sectorSize; 
	//每個byte裏面有幾個bit,一般情況下是8
    unsigned long byteSize; 
	//每個塊是多大byte,
    unsigned long regionSize;
	//這個bitmap總共有多少個塊
    unsigned long regionNumber;
	//這個塊對應了多少個實際的byte,這個數字應該是sectorSize*byteSize*regionSize
    unsigned long regionReferSize;
	//這個bitmap對應了多少個實際的byte,這個數字應該是sectorSize*byteSize*regionSize*regionNumber
    __int64 bitmapReferSize;
	//指向bitmap存儲空間的指針
    tBitmap** Bitmap; 
	//用於存取bitmap的鎖
    void* lockBitmap; 
} DP_BITMAP, * PDP_BITMAP;

​ 這裏在開頭可以看到,將 char 重命名爲 tBitmap,然後在最後創建了一個 tBitmap ** Bitmap 的指針元素,實際上等效於 **char ****。這樣做,是希望我們將 Bitmap看做一個指針數組。這個數組共有 regionSize個元素,每個元素就是一個指向內存塊的指針。這些指針首先指向空的內存塊(並不是實際上的,只是指針爲空)。看一下初始化bitmap的代碼。

NTSTATUS DPBitmapInit(
	DP_BITMAP **     bitmap,
	unsigned long       sectorSize,
	unsigned long       byteSize,
	unsigned long       regionSize,
	unsigned long       regionNumber
	)
{
	int i = 0;
	DP_BITMAP * myBitmap = NULL;
	NTSTATUS status = STATUS_SUCCESS;

	//檢查參數,以免使用了錯誤的參數導致發生處零錯等錯誤
	if (NULL == bitmap || 0 == sectorSize ||
		0 == byteSize || 0 == regionSize  || 0 == regionNumber)
	{
		return STATUS_UNSUCCESSFUL;
	}
	__try
	{
		//分配一個bitmap結構,這是無論如何都要分配的,這個結構相當於一個bitmap的handle	
		if (NULL == (myBitmap = (DP_BITMAP*)DPBitmapAlloc(0, sizeof(DP_BITMAP))))
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		//清空結構
		memset(myBitmap, 0, sizeof(DP_BITMAP));
		//根據參數對結構中的成員進行賦值
		myBitmap->sectorSize = sectorSize;
		myBitmap->byteSize = byteSize;
		myBitmap->regionSize = regionSize;
		myBitmap->regionNumber = regionNumber;
		myBitmap->regionReferSize = sectorSize * byteSize * regionSize;
		myBitmap->bitmapReferSize = (__int64)sectorSize * (__int64)byteSize * (__int64)regionSize * (__int64)regionNumber;
		//分配出regionNumber那麼多個指向region的指針,這是一個指針數組
		if (NULL == (myBitmap->Bitmap = (tBitmap **)DPBitmapAlloc(0, sizeof(tBitmap*) * regionNumber)))
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		//清空指針數組
		memset(myBitmap->Bitmap, 0, sizeof(tBitmap*) * regionNumber);
		* bitmap = myBitmap;
		status = STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		status = STATUS_UNSUCCESSFUL;
	}
	if (!NT_SUCCESS(status))
	{
		if (NULL != myBitmap)
		{
			DPBitmapFree(myBitmap);
		}
		* bitmap = NULL;
	}
	return status;
}

​ 可以看出,這裏使用了 DPBitmapAlloc 來分配內存,但是在後續中,使用了許多接口,並且較爲複雜,鑑於實際應用性不強,本人目前感覺學習意義不大,所以停止對該章的學習。

明日計劃

從明天開始慢慢啃文件系統的過濾與監控吧,似乎還挺有意思的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章