《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 来分配内存,但是在后续中,使用了许多接口,并且较为复杂,鉴于实际应用性不强,本人目前感觉学习意义不大,所以停止对该章的学习。

明日计划

从明天开始慢慢啃文件系统的过滤与监控吧,似乎还挺有意思的。

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