摘要:隨著計算機的普及和互聯網的發展,病毒、系統故障、誤操作等因素所帶來的數據丟失正在迅速增加,由此造成的損失也越來越嚴重,因此掌握數據恢復技術的變的越來越重要,而對磁盤、文件系統了解是進行數據恢復的必備知識。本文對Windows下如何直接讀取磁盤扇區進行了分析與研究,并結合Delphi實現了系統。
關鍵詞:磁盤;扇區;Delphi ;CreateFile;DeviceIoControl;SetFilePointer
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2009)24-6791-03
Read Floppy Disk Sector for Windows
WANG Hong
(Traditional Chinese Hospital of Luan, Luan 237006,China)
Abstract: With the popularization of computers and the development of the internet,the data missing because of the virus,system malfunction,misoperation and so on is increasing rapidly,the corresponding loss is also more and more severely,so it is very important to master the technology of resuming the data.understanding the disk and the file system is the necessary knowledge.this text analyze and study how to read the sector directly based on windows system,and realize the demo system by Delphi.
Key words: disk; sector; Delphi; CreateFile; DeviceIoControl; SetFilePointer
信息化時代,都越來越依賴于計算機進行工作。磁盤是存儲信息的主要介質之一,但由于病毒、系統故障、用戶的誤操作等原因,可能會造成數據的丟失,從而帶來嚴重的后果。哪么如何進行數據的恢復,成為非常重要的問題。了解磁盤的常識和操作系統的文件系統結構,并進而掌握系統下讀寫磁盤的方法,是進行數據恢復不可缺少的知識。 本文對如何通過Windows文件I/O函數對磁盤扇區的讀取進行了介紹。
1 基本概念
1.1 磁盤的尋址模式
硬盤的尋址模式,通俗地說,就是主板的BIOS通過什么方式,查找硬盤上某扇區的位置。隨著磁盤容量的變化,先后出現不同的的尋址模式,有CHS模式、LARGE模式、LBA模式等。現代大容量磁盤通常采用的是LBA線性尋址模式,但目前大多數的軟件中,使用的計算方法依然是相對比較簡單的CHS尋址模式,CHS尋址是硬盤尋址模式的基礎,仍具有實際意義。
1.2 FAT12文件系統介紹
磁盤存儲文件前要被操作系統格式化為指定的文件系統,根據磁盤的大小和系統的不同,格式化后的文件系統也有所差別,Windows系統可接受的文件格式有FAT、FAT32、NTFS等;為簡化問題,我們以傳統的3.5英寸的1.44M軟盤為例進行討論,硬盤經分區后,有邏輯盤和物理盤的區別,但理解了軟盤的文件系統,同樣有助于對硬盤進行處理。1.44M軟盤標準格式化后采用的是FAT12文件系統,邏輯上由以下幾個部分構成:
1.2.1 引導扇
磁盤0面0磁道第1扇區為引導扇,它包含兩部分內容:一是引導程序(BOOT),扇區的最后兩個字節為可引導標志,這2個字節如果是0x55,0xAA,機器啟動時會將這512字節讀取出來執行;二是該盤的基本參數表(BPB)。在BPB 中,有該盤卷的主要參數:磁頭數、每磁道的扇區數、總扇區數、每扇區的字節數等等。
1.2.2 文件分配表(FAT)
緊接著引導扇的是兩個完全相同的FAT表,第2個FAT是備用的。FAT表由一項項的文件分配項構成,每個文件分配表項占12位(bit),每個表項對應一個扇區,整個文件分配表的作用如下:
(1)相當于磁盤管理中的位示圖,用來記錄磁盤塊(簇)的使用情況。FAT 的一項對應磁盤上的一簇,若某項是非空標記表明磁盤上對應簇已被使用
(2)又起著鏈表的作用,若某項不是空(或一些特殊標記)則意思是某文件(或目錄)下一簇的內容在磁盤上的位置,相當于文件的物理結構是鏈接方式。
1.2.3 根目錄區
根目錄區用來存放根目錄下的各個文件和子目錄的目錄項(FCB)。每個目錄項占用32 個字節,用于記錄文件名、文件起始簇號、文件屬性等信息。
1.2.4 文件存放區
文件存放區用于存放普通文件和目錄文件(除根目錄以外)的內容。整個盤卷,去除引導扇、文件分配表和根目錄區所占用的扇區后,剩余的扇區就完全做為文件存放區使用了。
2 Windows下讀寫磁盤扇區方式
2.1 概述
由于Windows 操作系統采取了訪問安全保護機制,使得傳統的DOS下訪問硬件設備的方法不再適用。但Windows在采取“保護”措施的同時也提新的訪問硬件設備的方法。常用方法如下:
(1)Windows9X下利用INT21的AX=7305號子功能和AX=440D號子功能
(2)Windows9X下利用INT13的02、03號子功能
(3)利用VXD技術
(4)WindowsNT下把所有的硬件設備全部看做“文件”,并按照對文件的讀寫方式來對其進行數據存取訪問。
現行的Windows系統已遷移為NT平臺,故通常采用第4種方式,將磁盤設備當作一個“文件”進行讀寫。
2.2 Windows的文件I/O
在DOS操作系統下,最早的文件操作方法是使用FCB(文件控制塊),在高版本的DOS中,開始使用更方便的文件句柄方式,這種方式中程序指定一個包含全路徑的文件名后,就可以要求操作系統打開這個文件并返回一個文件句柄,以后就可以用這個句柄來讀寫文件,直到關閉文件為止。操作系統在內部為每個文件句柄維護一個讀寫指針,指示文件讀寫的位置,每次對文件的讀寫操作完成以后,指針會自動調整到本次操作的最后一個字節后面的位置。指針可以被移動到文件的任意位置,以便滿足隨機存取的要求。
Windows操作系統中,文件操作沿用了這種句柄方式,保留了文件句柄和讀寫指針等概念,Windows系統處理文件的一般步驟為:
(1)首先利用CreateFile()函數打開文件,并返回文件句柄;
(2)用SetFilePointer()函數調整文件指針,以決定下一次讀(寫)的起始位置;
(3)用用ReadFile()/WriteFile()函數從指定位置開始讀取(寫)文件;
(4)最后操作完成后用CloseHandle()關閉文件。
2.3 實現原理
當以系統規定的設備文件名作為參數調用CreateFile()函數,即可按文件讀寫的方式操作該設備,與普通文件名有所不同,設備驅動的“文件名”(常稱為“設備路徑”)形式固定為“\\\\.\\DeviceName”,DeviceName必須與設備驅動程序內定義的設備名稱一致。
通過CreateFile()打開的是整個磁盤邏輯分區,而要操作的是該分區的某些扇區,因此還要通過SetFilePointer()函數以文件操作的方式把指針移到要操作的磁盤扇區開始處。
在定位到要訪問的扇區開始位置后就可以通過ReadFile()或WriteFile()函數實施相應的讀寫訪問了,具體操作與文件讀寫并沒有什么太大的差別。最后,在完成訪問操作后以CloseHandle()關閉文件句柄釋放資源,從而完成一次完整的磁盤扇區數據訪問操作。
而磁盤的參數信息可通過函數DeviceIoControl來獲取。利用該接口函數向指定的設備驅動發送正確的控制碼及數據,然后分析它的響應,就可以達到我們的目的。
3 主要源程序
知道了Windows下訪問磁盤扇區的原理后,可以結合合適的高級語言實現具體的功能,下例給出Delphi下實現的主要數據結構和函數,程序清單如下:
//自定義數據結構,描述磁盤設備信息及句柄
TRawDrive=record
Disk_Geometry:TDisk_Geometry; // 磁盤設備的信息
Handle:THandle; // 打開磁盤設備時的句柄
end;
//自定義數據結構,對應MBR信息
TMbr=packed record
JmpBoot:array[0..2] of char;
OEM:array[0..7] of char;
BytesPerSec:Word;
SecPerClust:byte;
RsvdSecCnt:Word;
NumFATS:byte;
RootEntCnt:Word;
TotalSec16:Word;
Media:byte;
FatSz16:Word;
SecPerTrk:Word;
NumHeads:Word;
HiddSec:LongWord;
TotSec32:LongWord;
DrvNum:byte;
Reserved1:char;
BootSig:char;
VolID:array[0..3] of char;
VoLabel:array[0..10] of char;
FSType:array[0..7] of char;
tmp:array[0..447] of char;
EndLogo:array[0..1] of char;
end;
function OpenDrive(DriveLetter:Char;var RawDrive:TRawDrive):boolean;
//作用:打開指定磁盤,成功返回TRUE,失敗返回FALSE
//參數:DriveLetter指定欲打開的盤符;RawDrive返回磁盤信息
var
num:Cardinal;
begin
Result:=False;
//初始化結構
FillChar(RawDrive,Sizeof(TRawDrive),0);
//打開指定磁盤,并返回句句柄
RawDrive.Handle:=CreateFile(PChar('\\\\.\\'+DriveLetter+':'),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
Nil,
OPEN_EXISTING,
0,0);
//測試是否成功
if RawDrive.Handle=INVALID_HANDLE_VALUE then
exit;
//獲取磁盤信息
if not DeviceIoControl (RawDrive.Handle, IOCTL_DISK_GET_DRIVE_GEOMETRY , Nil,0, @RawDrive.Disk_Geometry,SizeOf(TDisk_GeoMetry),num,nil) then
exit;
Result:=True;
end;
procedure CloseDrive(var RawDrive: TRawDrive);
//作用:關閉打開的磁盤
//參數:RawDrive指定要關閉的磁盤結構信息
var num: Cardinal;
begin
CloseHandle(RawDrive.Handle);
RawDrive.Handle := 0;
end;
function ReadSectors(RawDrive:TRawDrive;Var Buf;Count:integer):boolean;
//作用: 讀取指定扇區,成功返回TRUE,失敗返回FALSE
//參數:RawDrive為要讀取的磁盤;Buf為存儲讀取數據的緩沖區;Count為要讀取的扇區個數
var
num:Cardinal;
begin
Result:=False;
if ReadFile(RawDrive.Handle,Buf,Count*RawDrive.Disk_Geometry.BytesPerSector,num,nil) then
ReSult:=True;
end;
function WriteSectors(RawDrive:TRawDrive;var Buf;Count:integer):boolean;
//作用: 寫入指定扇區,成功返回TRUE,失敗返回FALSE
//參數:RawDrive為要寫入的磁盤;Buf為存儲數據的緩沖區;Count為要寫入的扇區個數
var
num:Cardinal;
begin
Result:=False;
if WriteFile(RawDrive.Handle,buf,Count*RawDrive.Disk_Geometry.BytesPerSector,num,nil) then
Result:=True;
end;
4 總結
本文介紹了Delphi下結合Windows文件I/O函數直接讀取磁盤扇區的方法及原理,雖然針對的是FAT12文件系統,但知道了原理可以方便的擴展為針對其它文件系統的應用。
參考文獻:
[1] Steve Teixeira.Delphi 5開發人員指南[M].北京:機械工業出版社,2000,7.
[2] 飛思科技產品研發中心.Delphi下深入Windows核心編程[M].北京:電子工業出版社,2003,1.
[3] 羅云彬.Windows環境下32位匯編語言程序設計[M].北京:電子工業出版社,2002,10.
[4] 湯子瀛,等.計算機操作系統[M].西安:西安電子科技大學出版社,2001,8.
[5] 羅小平.Delphi精要[M].北京:電子工業出版社,2004,1.