您的当前位置:首页正文

不同Windows平台下磁盘逻辑扇区的直接读写

2021-12-12 来源:步旅网
维普资讯 http://www.cqvip.com

实用第一 智慧密集 % 张泽民 NULL); 一、概述 在DOS操作系统下,通过BIOS的INT13、DOS的INT'25 第二步:填充中断所用到的相关寄存器。这里将寄存器放 在一个结构中,结构定义如下(有关INT13使用的寄存器情 况,请参阅相关资料): tvpedef struct lNT1 3Regs{ (绝对读)、INT26(绝对写)等功能调用实现对磁盘逻辑扇 区或物理扇区的读写是很方便的,C语言中还有对应上述功能 调用的函数:biosdisk、absread和abswrite等=但在Windows 操作系统下编写WIN32应用程序时却再也不能直接使用上述 的中断调用或函数了。那么,在Windows操作系统下能不能实 现磁盘扇区的直接读写呢?如何实现磁盘扇区的读写呢?为了 解决这些问题,笔者在查阅了一些相关资料后发现.Windows 操作系统也提供了读写磁盘扇区的方法,只是在不同的版本中 有着不同的方式和使用限制 最后.笔者编写了一个磁盘扇区 直接读写类.希望能对大家有所帮助。 PVOID buffer: ,/eb ̄寄存器 BYTE Drive; //骏盐号d BYTE Head; /,/磁头号dh WORD ED×一High;//edx寄存鑫 BYTE Sector; //起始扇医CI BYTE Track; ,//磁道号ch WORD ECXHigh;//ecx寄存器 BYTE Numbe r; //要读写的扇取数al BYTE CMD / 命令。2一一读 3一一写 5一一格式化ah WORD EAX igh //eax寄存器 DWORD EDI; //edi寄存器 _二、一个读取软盘扇区的例子 Windows操作系统对所有的存储设备实行了统一管理,而 且为了安全起见,操作系统还不允许在WIN32应用程序(工 作在Pin 级)中直接调用中断功能,如INT13、INT21、 INT25、INT26等。但它同时也提供了一些服务来弥补这种缺 憾.在WIN95/98中,VWIN32服务就是其中一种。VWIN32 DWORD ESI DWORD EFLAG, ,/eai /flags l INT1 3 REGISTERS unsigned cha r Buffe r[51 2j./ 定义缓冲区.放萱读覃扇 区数据 INT13 REGISTERS reg={0}:,/定义寄存器结构夏量 reg buffe r=【void J BJffe r; reg D rire=0//0一转盘A 1一软盘B OxSO一硬盘C reg Head=0: reg Track=0 服务是通过一个VxD来实现的,它提供了设备10功能,使用 它所定义的一些控制命令字,WIN32应用程序可以实现诸如 DOS操作系统下的INT13、INT25、INT26和INT21等功能调 用,即通过使用API函数DeviceloControl向VWIN32发送控制 reg Sector=1 reg Numbe r=1, reg CMD=2,/,读鼋 命令,便可以实现WIN32应用程序和磁盘设备驱动程序间的 通信,从而实现对磁盘的存取。下面是VWIN32定义的一些控 制命令字: VWIN32 ̄DIOC 0S IOCTL (1)实现INT21功能 VWIN32 ̄OlOC_DOSjNT25 VW1N32 IOC_DOS_INI'26 VWIN32 IOC_DOS_[NT13 VWIN32_第三步:调用设备1o API函数DeviceloControl执行4号命 令(即VWIN32 IOC_DOSINTI3),BOOL b_ret=Devicelo— Control(hDev,4、&reg,sizeof(INT13 EGISTERS)、&leg、sizeof {INT13_BEG ̄TERS),&lpRet,0); {21实现INT25功能 (3)实现INT26功能 (4)实现INT13功能 如果其返回值不等于零,调用成功、进一步处理…调用失败。 第四步:关闭服务、CloseHandlelhDev1: 否则 DIOC OS_DRIVEINFO{6)实现INT21 730x功能 使用这些控制命令时,DevieelaControl函数的lpvInBuffer 和lpvOutBuffer需要指向一个寄存器结构的地址、该寄存器结 三、限制或局限 上面是使用INTI3读取软盘扇区的完整步骤、在WIN95/ 98下它是可以工作的。那么、是否将上面的寄存器结构中的 Drive置为Ox80就可以读取逻辑硬盘C盘的扇区了呢?回答是 否定的。INT13用来存取硬盘的功能在wind。w8中被忽略了。 另外,INT25、INT26虽然可以存取硬盘、但是它们不能工作 在FAT32格式的硬盘上。下面的列表将详细列举与磁盘操作 相关的中断调用的限制情况(不特殊说明,指的是在W/N95/ 构里面是执行中断命令必须的一些参数。如果要对磁盘进行读 写、只要使用DeviceloComml执行相应命令并设置相应的寄存 器即可。下面的例子用来读取软盘的一个扇区(使用 INT13): 第一步:打开VWIN32服务、HANDLE hDev=CreateFlie {”、、、\\\VWIN32”,0、0、0,0,FⅡ正且 G EI册DN工LOSE、 82:: 涵i 谴避 黼l 酗蠢黼要: ‘ 。’  1:: 。:} :”: : ‘…一 维普资讯 http://www.cqvip.com

实用第一 98操作系统下): 中断功能 限制及使用情况 智慧密集 //设置寄存器 reg EAX=0 ̄7305; // 能上美似于INT25.绝对读 INT13 FATl6 不可以读写硬盘,仅支持软盘 INT25/INT26 不可以读/写FAT32硬盘,支持FAT12、 reg EBX=fDw0RD)&d o //参数结构 地址 re9 ECX=一1 //必须是一1 reg EDX=1.,/注意:l丰[上倒不同,驱动器编 变了 0一一缺省1一一A、2一一B、3一一C reg ESi=0//ESI的bitO表示读写 0一一读、1一一 在写状态时SI的bitl一一bitl2,bitl5必须是0,bit13 INT21(440DH一41N/61N)不可甩(文档资料中说支持 FAT12、FAT1 6、FAT32,实际上没有实现) INT21【7305 ̄) 可以读写软盘、硬盘,支持FAT12、 bitl4、bitl5共同来表示所写数据的类型,具体见下表: 15 1413类型描述 0 0 0其它或不知道 0 0 1 FAT数据 0 1 0目录数据 0 l 1一般数据 I x x保留。bitl5必须是0。 第三步:调用API函数。BOOL bjet:DevieeIoControl (hDev,6,& reg, aize0f(D10cJ【EGIsTERS),& 工。昏 sizeof (DIOC EGISTERS),&cb.0); FAT16、FAT32,但要求WIN95OSR2及以后版本 值得一提的是上表中的INT21——7305H功能,它是专门 提供用来支持FAT32的,并且用来替换INT25/INT26,对应 的控制命令字是6(即VWIN32 DIOC_DOS DRIVEINFO),它 和INTI3、1NT25、INT26等中断功能的一个显著区剐是:它 不使用寄存器来传递参数(INT21——440DH一41H/61H类 同).而是使用一个称为D[SKIO的结构,寄存器EBX用来保 存指向该结构的地址。DISKIO的定义如下: typedef struct_pISKIO{ DWORD BwStartSector; //要读写的起始扇区号 第四步:关闭服务(同上)。 可以发现,两种方法读到的数据完全一致。 WORD wSecto rs; DWORD dwBuffer; )D}SKiO, PDiSKiO: //要读写的扇医数 //用来保毒读/写数据的缓冲区 四、WIN2000中的磁盘扇区读写 在WINNT和WIN2000中磁盘被看做一种标准设备 可 另外,在使用该功舶时还需要特别设置一些寄存器.如 ECX必须为一1.用ESI来表示读写。下面的例子是使用该功 能来实现上面的例子功能,即读软盘A的一个扇区。首先定 义一个新的寄存器结构供本例使用 typedef stra,ct_pIOC_REGISTERS{ DW0RD EBX DW0RD EDX; DW0RD ECX DW0RD EAX: DWORD EDI. DW0RD ESI: DWORD Fiags; 使用CreateFile粜打开文件一样打开并存取。CreateFile支持两 种方式的磁盘设备——逻辑磁盘(格式为“\\.\c:”)和物 理磁盘(格式为“\、.、PHYSICALDRIVEx”,其中x为数 字),例如打开A:盘进行读取操作,只要这样: HANDLE hDev=CreateFileI \\\\、\A: GENER lC_READ,FILE_sHARE:WRITE 0,OPEN_EXISTING.0.0 J, 如果得到的句柄有效,就可 使用ReadFfle来读取了。 ReadFilethDev,Buffer,51 2 &dwRet.0), 读取结束要关闭该句柄。 CloseHandle{hDevj. 1DIOC_REGISTERS. 其实该结构和上面的INT13 EGISTERS是一样的,只不 过INT13J ̄GISTERS将寄存器细分开了,可读性更强些。本 例 步骤上说和上面的例子相同,只有寄存器设置在内容上有 差异及使用的控制命令字不同(下面有详细的注释标明这些不 同)。 这比WIN95/98下的磁盘扇区读取方便多了。 另外,上面的例子是操作逻辑磁盘的,它包括软驱、硬盘 分区等;物理磁盘指的是实际的硬盘,它不关心该硬盘被分成 几个区,硬盘的编号是从0开始的, “\\.、PHYSI CALDRIVEO”表示第一块硬盘 其它依此类推 大家可能马 上会想起,利用这种机制可以对硬盘的分区表进行存取了。确 实如此,此时便可以对硬盘的主引导扇区(独立存在的一个扇 区,包含分区表信息,不同于磁盘分区的BOOT区)进行操作 了。 unsigned thai Buffer1 512】=IO , HANDLE hDev=CreateFilef \\、\\\PHYSlCALDRlVE0 GENERIC WRITE.第一步:打开VWIN32服务(同上)。 第二步:设置寄存器。 DIOC REGISTERS reg={0). DISKIO dio; unsigned char Buf ̄er[51 2】, //设置参数结构 dio dwStartSector:0,//注意:和上倒不同,不是1,从0 开始编号 dio wSectors =1 FI LE SHARE RITE.0 OPEN_EXISTING. O.0), WriteFile l hDev,Buffer 51 2,&dwRet.0) CloseHanne{hDev}: dio dwBu仟er =【DWORD}Buffer 维普资讯 http://www.cqvip.com

实用第一 智慧密集 五、一个自适应的磁盘读写类 由上面的例子可以看出,不同的操作系统下对磁盘扇区的 六、补充说明 严格来说,在对磁盘进行读写时,应该遵循以下顺序:打 开设备(WIN95/98下为VWIN32服务,WIN2000下为磁盘设 备)、锁卷、验证卷的有效性、读/写、开锁卷、关闭设备。 读写有不同的方式,为了能够在各类操作系统下能够使用统一 的方法读写磁盘扇区,特设计了一个通用类。该类的设计思想 如下:首先编写各类操作系统下的磁盘扇区存取函数,然后通 过GetVersioru ̄来翔断操作系统,进而选取对应的函数来实现 磁盘扇区的读写。由上面的分析可知,Win&ws操作系统对 INT13的支持是最差的,所以在这里只使用INT25、INT26、 这里为了描述上的简洁,忽略了锁卷/开锁卷及验证有效性等 操作。有兴趣的朋友可以la行添加 另外,该类仅实现了逻辑驱动器的读写,要想实现诸如对 物理硬盘的主引导扇区的读写,还需要其它技术,如thunk技 lNT21一一7305等中断调用来实现非NT的Windows操作系 统,WIN2000等NT类操作系统可以直接读写。类的定义如 下: class CDisktnfo{ public: CDisMnfo_I: 一CDiskinfo c]: private: HANDLE hDev;//非NT类WINDOWS操作系统用 DW0RD dwCurrentP}atfOrm void GetPlatform 1]://取得操作系统.并存A变量dwCur- re n1PIatfOrm B00L Win2000_AccessSectors fWORD CMD BYTE bDrive.DWORD dwSta rtSecto r.WORD wSecto rs.LPBYTE IpSectBuff1.//用于wIN2000、WINNT等操作系统. B00L]nt25 ReadSecto rs cBYTE bDrive.DWORD dw. StartSector.WORD wSectors.LPBYTE IpSectBuff), BOOL Int26_yvriteSectors【BYTE bDrive.DWORD dwStartSec・ tor.WORD wSectors.LPBYTE]pSectBuff】.//用于WIN95 前的操作系筑 B00L]nt21 AccessSectors{WORD CMD BYTE bDrive. DWORD dwStartSector WORD wSec ̄ra LPBYTE]pSect- BuffI.//7305功能实现.用于wIN950SR2、WIN98每操作系统 pubiic: //对 统一提供Read和W rite操作 娄内部根据平台选 用适台的函数调用 BOOL ReadSectors(BYTE bD rive.DWORD dwStartSec. tor WORD wSectors LPBYTE]pSectBuff) B0OL WriteSectors{BYTE bDrive DWORD dwStart- Sector WORD wSectors,LPBYTE]pSectBuff): }. 该类对外提供了两个接口,即Readsect町s和Wfi ̄See- Iters,其参数是一样的,分别是要读写的磁盘编号bDrive,要 存取磁盘的开始扇区号dwStartSector,要读取的扇区数wSec- tots和读写扇区数据的缓冲区IpSvctBtff 这里磁盘编号是从1 开始的.即l代表A:,2代表B:.3代表c:,依此类推。扇 区的编号从0开始 使用时也很简单.只要作如下声明即可: BYTE Buffer{1024】 CDisklnfo A: BOOL bRet=A ReadSectors(1.0.2.Buffe r) 详细情况见附带的类文件及掇I试程序。 术,即缩写两个动态库,一个是WIN32动态库,一个是 WIN16动态库(thunk技术只可以用动态库实现).其中 WIN16动态库转到DPMI模式,调用INT13(或者扩展 INT13)来实现物理磁盘扇区的读写。其调用过程如下: WIN32程序——调用WIN32动态库的接口函数—— WIN32动态库接口函数中再调用WIN16提供的接口函数—— WIN16动态库中的接口函数调用INT13实现WIN32程序的请 求——对物理磁盘的读写。有关thunk技术请参阅相关文档资 料。 所有的例子在w删98、WIN2000操作系统、VC6集成环 境下调试通过。 (收稿B期:2002年3月28日) 

因篇幅问题不能全部显示,请点此查看更多更全内容