第 11 章
创建备份副本
为什么需要备份?
“预防总是比治疗更好。”备份也是数据防灾的重要组成部分,它可以帮助我们克服磁盘故障或任何其他类型的数据丢失。在本章中,我们将讨论如何在发生严重磁盘故障后仅使用以前的备份来恢复数据。
使用以前保存的备份进行恢复几乎总是高达 100%,但是,在某些特定情况下,不同类型的磁盘故障可能会导致恢复结果的差异。
使用备份恢复数据是一个相当简单、快速和可靠的过程,可以提供最佳结果,而在没有备份的情况下恢复数据则很复杂、令人困惑并且会花费大量时间,即便如此,在很多情况下我们担心无法获得 100% 的数据。
何时预订以及预订哪些内容
磁盘上有几个不同的区域需要复制一次或以不同的时间间隔复制。下表概述了完整备份所涉及的步骤,并帮助您确定何时备份以及备份什么:
需要保留的内容 |
何时需要备份? |
MBR 备份 |
在 FDISK 之后。 MBR 由 FDISK DOS 命令创建。您可以在 FDISK 之后备份 MBR,但是即使格式化 FDISK 创建的分区后,MBR 仍然保持不变。 |
DBR备份 |
格式化后,为每个逻辑磁盘创建一个DBR备份。 |
备份 FAT 条目和目录。 |
每次创建或删除文件或目录时,FAT 和目录条目都会发生变化。因此建议每天进行备份。 |
备份用户数据 |
应定期进行。这种类型的备份会导致创建磁盘映像。然而,这很耗时,但大多数驱动器上拥有非常敏感数据的公司都愿意花时间创建磁盘映像,因为这样他们就可以备份上述所有信息。 |
另外,您还应该为系统制作一个紧急启动盘。如果您的硬盘上的数据发生任何意外,您将能够使用此软盘启动系统并分析驱动器中的错误。
备份 MBR(主引导记录)及其用法
主引导记录 (MBR),有时也称为主分区表 (MPT),包含一个小程序,用于从硬盘加载和运行活动(或可引导)分区。主引导记录包含有关所有四个主分区的信息。
有关 MBR 的详细讨论,请参阅本书前面讨论的“磁盘和操作系统的逻辑方法”一章。
MBR 位于绝对扇区 0,或者说位于柱面 0、磁头 0 和扇区 1。它是通过执行 FDISK.EXE DOS 命令在硬盘上创建的。
为什么要备份MBR:
MBR 允许活动分区的引导扇区在系统启动时获得控制权。
开机自检(POST)后,BIOS将硬盘中的MBR(主引导记录)加载到内存中并执行。首先,MBR 检查硬盘上是否有活动分区,然后将 DOS 引导记录 (DBR) 加载到内存中并将控制权传递给操作系统引导代码,然后操作系统引导记录代码将操作系统的其余部分加载到内存中。
因此,我们可以说,如果磁盘的MBR损坏,硬盘实际上就坏了,系统完全无法启动或运行操作系统。在这种状态下,硬盘上存储的所有数据都变得无法访问。通常,错误消息显示如下:
“无效的分区表”“加载操作系统时出错”“缺少操作系统”
使用 MBR 备份可以恢复什么?
备份 MBR 可以帮助您摆脱上述错误消息。使用备份,您可以修复以下问题:
- 由于 IPL(初始程序加载器)损坏,导致加载操作系统时出错
- 丢失主分区
- 分区信息损坏
- 错误的魔法数字
编写程序来创建 MBR 备份:
/* 创建 MBR 备份的程序 */
#包括 <bios.h>
#包括 <stdio.h>
int main(空)
{
结构diskinfo_t dinfo; /* 存储结构
磁盘参数信息 */
结果 int;
整数个数=0;
char 文件名[80]; /* 保存给定的文件名
用户 */
static char dbuf[512]; /* 512 字节的数据缓冲区 */
文件*fp;
dinfo.drive = 0x80; /* 第一块硬盘的驱动器号
磁盘 */
dinfo.head = 0; /* 磁盘头号 */
dinfo.track = 0; /* 轨道号 */
dinfo.sector = 1; /* 扇区号 */
dinfo.nsectors = 1; /* 扇区数 */
dinfo.buffer = dbuf; /* 数据缓冲区 */
printf("\n输入要存储的文件名和路径
MBR 的备份\n");
获取(文件名);
// 打开文件以存储 MBR 备份 \\
如果((fp = fopen(文件名,“wb”))==NULL)
{
printf("无法创建文件,请按任意键
出口...”);
获取();
退出(0);
}
printf("尝试从硬盘驱动器读取:\n");
//// 读取指定磁盘扇区\\\\
结果 = _bios_disk(_DISK_READ,&dinfo);
如果 ((结果 & 0xff00) == 0)
{
printf("从硬盘驱动器读取的磁盘:
成功。\n”);
/// 将 512 字节的 MBR 写入文件 \\\\
while(计数<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff );
计数++;
}
fclose(fp);
}
别的
printf("无法读取硬盘驱动器,状态 = 0x%02x\n", result);
返回0;
}
程序编码注释:
在前面给出的程序编码中,基本上我们正在逐步执行以下任务:
- dinfo 指向 diskinfo_t 结构,该结构包含 _bios_disk 函数执行操作所需的参数信息。
- 由于我们要读取磁盘的第一个扇区,因此该扇区的位置如下:
范围 |
含义 |
dinfo.驱动器 = 0x80 |
它表示物理驱动器80H是第一个硬盘驱动器。 |
dinfo.head = 0 |
它指向0号头 |
dinfo.track = 0 |
它指向0 号轨道 |
dinfo.扇区 = 1 |
软盘的第一个扇区,即扇区1 |
dinfo.扇区 = 1 |
>读取操作要考虑的扇区数 = 1 |
dinfo.buffer = dbuf |
操作的数据缓冲区 |
- 打开一个用户给定文件名和路径的文件流,用于存储精确 512 字节的 MBR 备份。文件名和路径存储在字符数组 filename 中。
- _bios_disk(_DISK_READ, &dinfo) 读取硬盘的第一个扇区(80H),由 dinfo 指定。
- 返回的状态存储在结果中,用于显示操作成功的消息或如果发生任何错误则在屏幕上显示错误消息。
从备份恢复 MBR 的程序:
如果 MBR 以任何方式损坏,接下来给出的程序有助于恢复 MBR。
应始终牢记,非法使用或不了解情况使用该程序可能会破坏硬盘中的数据信息,并可能导致整个数据无法访问。您应该清楚自己要做什么。否则,问题可能会变得更加复杂。
从备份恢复 MBR 的程序:
程序编码如下:
/* 从备份文件恢复 MBR 备份的程序 */
#包括 <bios.h>
#包括 <stdio.h>
int main(空)
{
结构diskinfo_t dinfo;
int 结果;
int计数=0;
char filename[80]; /* 存储给定的文件名
由用户 */
static char dbuf[512]; /* 512 字节的数据缓冲区
*/
文件*fp;
/* 获取用户输入的 MBR 备份文件路径 */
printf("\n输入备份文件的文件名和路径
MBR \n“);
获取(文件名);
如果((fp = fopen(文件名,“rb”))==NULL)
{
printf("无法打开备份文件,请按任意键
退出...”);
获取();
退出(1);
}
/* MBR 数据应精确为 512 字节 */
while(计数<512)
{
fscanf(fp,"%c",&dbuf[count]);
计数++;
}
fclose(fp);
printf("正在尝试写入硬盘驱动器:\n");
dinfo.drive = 0x80; /* 第一个驱动器号
硬盘 */
dinfo.head = 0; /* 磁盘头号 */
dinfo.track = 0; /* 轨道号 */
dinfo.sector = 1; /* 扇区号 */
dinfo.nsectors = 1; /* 扇区数 */
dinfo.buffer = dbuf; /* 数据缓冲区 */
结果 = _bios_disk(_DISK_WRITE, &dinfo);
如果 ((结果 & 0xff00) == 0)
{
printf("将 MBR 备份恢复到磁盘
扇区:成功。\n");
}
别的
printf("无法写入硬盘驱动器,状态 =
0x%02x\n",结果);
返回0;
}
程序编码注释:
在上面给出的程序编码中,基本上我们正在逐步执行以下任务:
- dinfo 指向 diskinfo_t 结构,该结构包含 _bios_disk 函数执行操作所需的参数信息。
- 因为我们想要在磁盘的第一个扇区上写入,因此该扇区的位置如下:
范围 |
含义 |
dinfo.驱动器 = 0x80 |
它表示物理驱动器80H是第一个硬盘驱动器。 |
dinfo.head = 0 |
它指向0号头 |
dinfo.track = 0 |
它指向0 号轨道 |
dinfo.扇区 = 1 |
软盘的第一个扇区,即扇区1 |
dinfo.扇区 = 1 |
读取操作要考虑的扇区数 = 1 |
dinfo.buffer = dbuf |
操作的数据缓冲区 |
- 用户指定的 MBR 备份文件名和路径存储在字符数组 filename 中。需要注意的是,MBR 信息应精确为 512 字节。
- _bios_disk(_DISK_WRITE, &dinfo) 将数据写入硬盘的第一个扇区(80H),由 dinfo 指定。
- 返回的状态存储在结果中,用于显示操作成功的消息或如果发生任何错误则在屏幕上显示错误消息。
DBR(DOS引导记录)的备份及其使用
在分区表之后,DOS 引导记录 (DBR) 或有时称为 DOS 引导扇区是硬盘上第二重要的信息。
有关 DBR 的详细研究,请参阅本书前面讨论的“磁盘和操作系统的逻辑方法”一章。
每个 DOS 分区的第一个逻辑扇区将包含一个 DOS 引导记录 (DBR) 或 DOS 引导扇区。DBR 的作用是将操作系统从硬盘驱动器加载到计算机的主内存中,并将系统的控制权交给已加载的程序。
硬盘上第一个分区的 DOS 引导记录 (DBR) 通常位于绝对扇区 63(磁盘驱动器上的第 64 个扇区)或以 CHS 形式存在,对于大多数驱动器,我们可以说 C–H–S = 0–1–1。
但是,此位置可能因驱动器的 SPT(每磁道扇区数)而异。例如,在旧的 245MB 驱动器上,只有 31 个 SPT,引导记录位于第 32 个扇区(绝对扇区 31)。
DBR 是在使用 FDISK 命令进行分区后由 DOS 的 FORMAT 命令创建的。DBR 所在的扇区将成为 DOS 中该特定分区的逻辑扇区 1。DOS 使用的扇区编号从 DBR 所在的物理扇区开始。
DBR 包含一个小程序,由主引导记录 (MBR) 可执行程序执行。所有 DOS 分区都包含用于引导机器(即加载操作系统)的程序代码,但只有该分区由主引导记录控制,在分区表条目中指定为活动分区。
为什么要备份DBR:
DBR 包含有关磁盘几何结构的一些重要信息。此信息位于每个分区的第一个扇区中,例如:
- 跳转代码 + NOP
- OEM 名称和版本
- 每扇区字节数
- 每簇扇区数
- 保留扇区
- FAT 副本数
- 最大根目录条目数(但不适用于 FAT32)
- 分区中的扇区数小于 32MB(因此不适用于 FAT32)
- 媒体描述符(硬盘为 F8H)
- 每个 FAT 的扇区数(在较旧的 FAT 系统中,不适用于 FAT32)
- 每磁道扇区数
- 磁头数量
- 分区中隐藏扇区的数量
- 分区中的扇区数
- 每个 FAT 的扇区数
- FAT 信息描述符标志
- FAT32 驱动器版本
- 根目录起始簇号
- 文件系统信息扇区的扇区号
- 备份引导扇区的扇区号
- 预订的
- 分区的逻辑驱动器号
- 扩展签名(29H)
- 分区序列号
- 分区的卷名
- FAT 名称
- 可执行代码
- 可执行标记或幻数 (AAH 55H)
一般情况下,屏幕上会显示以下错误信息:
“磁盘启动失败”
“非系统磁盘或磁盘错误”
“无效的系统磁盘或磁盘 I/O 错误”
“更换磁盘,然后按任意键…”
使用 DBR 备份可以恢复什么?
DBR 备份可能有助于您摆脱上述错误消息。屏幕上的这些错误消息等待用户将包含上述程序的可启动磁盘放入软盘驱动器并按下某个键。
如果您从可启动软盘或 CD 启动系统,则驱动器应该可以访问。虽然硬盘不可启动,但通常不会影响对磁盘驱动器数据的访问。使用可启动磁盘启动系统后,您就可以访问数据。
通过恢复 DBR 的备份,您可以克服上述产生的问题。
制作和恢复 DBR 备份的程序:
用于制作 DBR 备份和恢复它们的程序与 MBR 备份和恢复的程序几乎类似。
例如,如果您要编写程序来备份磁盘第一个逻辑驱动器的 DBR 并将其恢复,则 dinfo 结构指定的参数将更改如下:
范围 |
含义 |
dinfo.驱动器 = 0x80 |
它表示物理驱动器80H,即第一个硬盘驱动器> |
dinfo.head = 1 |
它指向1号头 |
dinfo.track = 0 |
它指向0 号轨道 |
dinfo.扇区 = 1 |
软盘的第一个扇区,即扇区1 |
dinfo.扇区 = 1 |
读取操作要考虑的扇区数 = 1 |
dinfo.buffer = dbuf |
操作的数据缓冲区 |
这里我们看到只有读写扇区的位置发生了变化。这里 CHS 被指定为 0-1-1,因为第一个逻辑驱动器的 DBR 存储在这里。
完整的磁盘映像
如今,这种备份方式越来越流行,最受系统中有敏感数据的组织的青睐。他们不能冒哪怕一丁点数据丢失的风险。
这些组织定期将他们的备份作为整个磁盘映像。虽然这需要一些时间,但可以保证你不会错过任何东西。由于其日益普及,程序员已尽最大努力使磁盘映像软件越来越快,以最大限度地缩短映像过程所需的时间。
磁盘映像是一个好主意,因为只需花几十分钟,您就可以放心地备份口袋中的所有内容。所有因素(如 MBR、BDR、FAT、根目录)都会原封不动地复制到目标磁盘。
磁盘映像需要与存放宝贵数据的源硬盘完全相同(或几乎完全相同)的目标硬盘。始终要记住的一点是,目标磁盘不应小于源磁盘。
拍摄完整的映像后,如果您使用拍摄了磁盘映像的目标磁盘启动系统,通常您将获得所有原样的数据。
编写完整磁盘映像程序
接下来给出了磁盘映像程序。该程序使用 INT 13H 扩展,因此它也可以支持大磁盘。
该程序将第一个物理硬盘驱动器 (0x80) 的映像制作到第二个物理硬盘驱动器 (0x81),因此在制作备份映像之前,您应该记住目标磁盘 (0x81) 中的所有数据将被源磁盘 (0x80) 的数据按扇区模式覆盖。
该程序的编码如下所示:
/* 程序将第一个硬盘(0x80)的映像制作到第二个硬盘(0x81) */
#include<stdio.h>
#include<dos.h>
#包括<conio.h>
/* 使用 INT 13H 扩展、功能编号 0x48 的 getdrivegeometry 函数使用的结构。 */
结构几何
{
unsigned int size ; /*(调用)缓冲区的大小 */
unsigned int flags ; /* 信息标志 */
unsigned long cyl; /* 物理数量
驱动气缸 */
无符号长头;/* 物理数量
头部驶入驾驶舱 */
unsigned long spt; /* 物理数量
每磁道扇区数 */
无符号长整型扇区[2];/*总数
驱动器上的扇区 */
unsigned int bps ; /* 每扇区字节数 */
};
/* 磁盘地址包格式的结构,供 readabsolutesectors 和 writeabsolutesectors 函数使用 */
磁盘加载包结构
{
char packetsize;/*数据包的大小,一般为10H*/
char reserved; /* 保留 (0) */
int blockcount ; /* 要传输的块数 */
char far *bufferaddress ; /* 要传输的地址
缓冲 */
无符号长整型块号[2];/* 起始绝对
区块编号 */
};
///// 获取驱动器参数的函数 \\\\\
无符号长整型 getdrivegeometry (int drive)
{
联合 REGS i,o;
结构 SREGS s;
结构几何 g = { 26, 0, 0, 0, 0, 0, 0, 0 };
ihah = 0x48 ; /* INT 13H 的功能编号 0x48
扩展查看评论
以下 */
ihdl = drive; /* 驱动器号 */
ixsi = FP_OFF((void far*)&g);
s.ds = FP_SEG((void far*)&g);
/* 使用段寄存器值调用 INT 13H 扩展的指定功能号 */
int86x ( 0x13,&i,&o,&s ) ;
printf("\n 磁头 = %lu, 每磁道扇区数 = %lu, 柱面数 =
%lu\n", g.heads, g.spt, g.cyl);
/* 如果获取驱动器几何函数失败,则显示错误消息并退出 */
如果(g.spt==0)
{
printf("\n获取驱动器几何功能失败....");
printf("\n 扩展不支持,按任意键
出口...”);
获取();
退出(1);
}
返回 *g.sectors; /* 返回扇区数
在驱动器上 */
}
////// 主程序开始 \\\\\\
空主()
{
无符号长循环=0,Sectors_in_HDD1=0,Sectors_in_HDD2=0;
unsigned char buffer[61440]; /* 61440 的数据缓冲区
每次读取/写入 120 个 512 字节扇区以节省时间。 */
字符选择;
clrscr();
/* 如果连接的硬盘总数少于两个,则显示错误消息并退出。 */
如果(((char)peekb(0x0040,0x0075))<2)
{
printf("\n\n 您必须至少有两个硬盘
连接到您的计算机来运行此程序”);
printf("\n 程序。按任意键退出... ");
获取();
退出(1);
}
/// 获取第一个硬盘的参数(0x80)\\\
Sectors_in_HDD1 = 获取驱动器几何形状 (0x80);
printf(" 第一个硬盘中的总扇区数 = %lu\n\n",
HDD1中的扇区);
/// 获取第二个硬盘的参数 (0x81) \\\
Sectors_in_HDD2 = 获取驱动器几何形状 (0x81);
printf(" 第二块硬盘的总扇区数 = %lu\n\n",
HDD2 中的扇区);
/// 先确认,再继续 \\\
printf("\n 第二块硬盘上的所有数据将被
丢失的 !!!”);
printf("\n 按 \'Y\' 继续,否则按任意键
出口... ”);
选择 = getche();
开关(选择)
{
案例 ‘y’:
案例‘Y’:
休息;
默认:
退出(0);
}
/* 目标不应小于源 */
如果(HDD2 中的扇区 < HDD1 中的扇区)
{
printf("\n\n 目标磁盘不应小于
比源磁盘”);
printf("\n按任意键退出...");
获取();
退出(0);
}
/* 如果一切正常,将源磁盘的所有扇区复制到目标硬盘 */
gotoxy(10,15);printf("复制绝对扇区:");
对于(循环=0;循环<=Sectors_in_HDD1;循环=循环+120)
{
读取绝对扇区(0x80,循环,120,缓冲区);
写入绝对扇区(0x81,循环,120,缓冲区);
gotoxy(36,15);printf(“%ld”,循环);
如果(kbhit())
{
退出(0);
}
}
//// 显示完成消息 \\\
printf("\n\n 磁盘映像现已完成,按任意键
退出...”);
获取();
}
//// 主要内容结束
编码评论:
在前面给出的程序编码中,对于磁盘映像,我们将执行以下操作:
- 结构 geometry 由 getdrivegeometry 函数使用,使用 INT 13H 扩展,函数编号 0x48。有关 INT 13H 扩展的详细说明,请参阅本书前面讨论的“处理大硬盘”一章。
代表磁盘几个参数的数据类型含义如下:
数据类型 |
大小(以字节为单位) |
描述 |
无符号整数大小 |
2 个字节 |
缓冲区大小 |
无符号整数标志 |
2 个字节 |
信息标志 |
无符号长整型 |
4 字节 |
驱动器上的物理柱面数 |
未签名的长头 |
4 字节 |
驱动器上的物理磁头数量 |
无符号长整型spt |
4 字节 |
每磁道的物理扇区数 |
无符号长扇区[2] |
8 字节 |
驱动器上扇区总数 |
无符号整数bps |
2 个字节 |
每扇区字节数 |
- 结构体 diskaddrpacket 被 readabsolutesectors 和 writeabsolutesectors 函数使用。磁盘地址包的格式如下表所示:
数据类型 |
大小(以字节为单位) |
描述 |
字符数据包大小 |
1 字节 |
Packet 大小,一般为 10H |
字符保留 |
1 字节 |
保留 (0) |
整数块数 |
2 个字节 |
要传输的块数 |
char far *缓冲区地址 |
4 字节 |
传输缓冲区地址 |
无符号长整型块号[2] |
4 字节 |
起始绝对块号 |
- getdrivegeometry 函数用于获取指定驱动器的参数。getdrivegeometry 函数使用 INT 13H Extensions 的函数号 0x48。
参数含义如下表所示:
范围 |
含义 |
伊哈 = 0x48 |
INT 13H 扩展的功能编号 0x48 |
ihdl =驱动器 |
驱动器号 |
ixsi = FP_OFF((void far*)&g) |
ds:si前面讨论过的驱动器参数缓冲区地址 |
s.ds = FP_SEG((void far*)&g) |
ds:si前面讨论过的驱动器参数缓冲区地址 |
int86x(0x13, &i, &o, &s) 函数使用段寄存器值调用中断 13H。getdrivegeometry 函数返回驱动器上的总数。
- 在main()函数中,(char)peekb(0x0040, 0x0075);(函数peekb在DOS.H中定义)返回连接到系统的硬盘数量。
连接到系统的硬盘数量由存储在内存位置 0040H:0075H(段 0040H:偏移量 0075H)的字节表示。如果连接到系统的硬盘数量少于两个,则程序会显示错误消息并退出。
Sectors_in_HDD1 = getdrivegeometry (0x80);获取第一个硬盘(0x80)的参数并返回第一个硬盘上的总扇区数。
类似地,Sectors_in_HDD2 = getdrivegeometry (0x81);获取第二块硬盘(0x81)的参数并返回第二块硬盘上的总扇区数。
在用户确认继续进行映像处理后,首先检查源硬盘的大小是否不能大于目标硬盘的大小。如果目标硬盘较小,则显示错误消息并退出。
如果一切顺利,将源磁盘的扇区复制到目标磁盘。这里我们一次读写 61440 字节(120 个扇区,每个扇区 512 字节),以加快映像过程。
如果想一次性使用更多扇区,甚至超过 64K 的限制,可以在大内存模型中使用“大指针”来实现。规范示例如下:
char 巨大数组[100000L];
- 函数 readabsolutesectors ( 0x80, loop, 120, buffer ); 从无符号长整数 loop 指定的扇区号开始读取第一个硬盘(0x80)的 120 个扇区,并将数据存储在数据缓冲区中。
- 函数 writeabsolutesectors ( 0x81, loop, 120, buffer );将数据缓冲区的数据写入第二块硬盘 (0x81) 的 120 个扇区,从无符号长整数 loop 指定的扇区号开始。
函数readabsolutesectors ( ) 和 writeabsolutesectors ( )的代码如下所示:
//// 读取绝对扇区的函数\\\\
int readabsolutesectors(int drive,
无符号长整型扇区号,
int 扇区数,
无效*缓冲区)
{
联合 REGS i,o;
结构 SREGS s;
结构磁盘地址包 pp;
pp.packetsize = 16 ; /* 数据包大小 = 10H */
pp.reserved = 0 ; /* 保留 = 0 */
pp.blockcount = numofsectors ; /* 扇区数
阅读 */
/* 用于数据缓冲区 */
pp.bufferaddress = (char far*)MK_FP(FP_SEG((void
far*)缓冲区),FP_OFF((void far*)缓冲区));
pp.blocknumber[0] = sectornumber ; /* 扇区号
阅读 */
pp.blocknumber[1] = 0 ; /* 块号 */
ihah = 0x42 ; /* 功能编号 */
ihdl = drive ; /* 物理驱动器号 */
ixsi = FP_OFF((void far*)&pp); /* ds:si 用于
缓冲区参数 */
s.ds = FP_SEG((void far*)&pp); /* ds: 说
缓冲区参数 */
/* 使用段寄存器值调用 INT 13H 的指定函数 */
int86x ( 0x13,&i,&o,&s ) ;
如果(oxcflag==1)
返回 0 ; /*失败 */
别的
返回 1 ; /* 成功 */
}
//// 写入绝对扇区的函数 \\\\
int writeabsolutesectors(int 驱动器,
无符号长整型扇区号,
int 扇区数,
无效*缓冲区)
{
工会规章 i, o ;
结构 SREGS s;
结构磁盘地址包 pp;
pp.数据包大小 = 16 ; /* 数据包大小 = 10H */
pp.保留 = 0 ; /* 保留 = 0 */
pp.块数 = 扇区数; /* 扇区数
将被写入 */
/* 用于数据缓冲区 */
pp.bufferaddress = (char far*)MK_FP(FP_SEG((void
far*)缓冲区),FP_OFF((void far*)缓冲区));
pp.blocknumber[0] = sectornumber ;/* 扇区号
将被写入 */
pp.块号[1] = 0 ; /* 块号 = 0 */
ihah = 0x43; /* 功能编号 */
ihal = 0x00; /* 标志条目,参见
评论 */
ihdl = 驱动器; /* 物理磁盘号 */
/* ds:si 为缓冲区参数 */
ixsi = FP_OFF((void far*)&pp);
/* ds:si 为缓冲区参数 */
s.ds = FP_SEG((void far*)&pp);
/*用段寄存器的值调用指定的INT 13H函数*/
int86x ( 0x13,&i,&o,&s ) ;
如果 ( oxcflag == 1 )
返回 0; /* 失败 */
更多的
返回 1; /* 成功 */
}
编码注释:
两个函数使用的参数含义如下:
范围 |
大小(以字节为单位) |
描述 |
pp.数据包大小 = 16 ; |
1 字节 |
封装尺寸 = 10H |
pp.保留 = 0 ; |
1 字节 |
保留 = 0 |
pp.块数 =扇区数; |
2 个字节 |
要读取的扇区数 |
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void far*)buffer), FP_OFF((void far*)buffer)); |
----- |
用于数据缓冲区或传输缓冲区 |
pp.块号[0] =扇区号; |
4 个字节 |
要读取/写入的扇区号(通常我们只需要这个)。仅可单独使用。最多可支持 2.1 TB。 |
pp.块号[1] = 0 ; |
4 个字节 |
区块编号。如果您要访问大于 2.1 TB 的磁盘,请使用它。 |
ihah = 0x42;或 ihah = 0x43 ; |
2 个字节 |
功能 扩展数 INT 13H |
ihal = 0x00 ; |
1 字节 |
写标志只在写功能中使用,00H、01H用于不带验证的写,02H用于带验证的写。 |
ihdl =驱动器; |
2 个字节 |
物理磁盘号 |
ixsi = FP_OFF((void far*)&pp); |
------ |
ds:si 为缓冲区参数 |
s.ds = FP_SEG((void far*)&pp); |
------ |
ds:si 为缓冲区参数 |
int86x ( 0x13,&i,&o,&s ) ; |
------ |
使用段寄存器值调用指定的INT 13H函数 |