一、引言
在DOS系统下,在计算机应用培训中因培训要求不同, 对软件的要求也不同,由于学员的误操作,存放在硬盘上的软件和重要数据容
易被非法删除或受到损坏。对此,笔者通过对硬盘管理的深入分析和实践,总结出了在硬盘上备份、保护重要数据和软件的一种新的行之
有效的方法:建立多个PRI DOS 分区, 不同的培训要求使用不同的PRI DOS分区,在使用时同时只有一个PRI DOS 分区可供使用, 其余
PRI DOS分区均被隐含。
二、分区表结构
众所周知,DOS操作系统下,一个硬盘可以分为PRI DOS分区和扩展分区两大部分,而扩展分区中又可进一步建立多个逻辑分区。这些
PRI DOS分区和逻辑分区都可象单独的物理硬盘一样使用。那么DOS是怎样实现对这些分区的管理和使用的呢?DOS 管理硬盘的秘密是两个
表:硬盘分区表链。系统在启动过程中,DOS 根据硬盘分区表链及分区表提供的分区信息建立了各个分区的磁盘参数表(BPB表),而磁盘
参数表是DOS访问硬盘的基础。 因此分区表链及分区表在硬盘存取中具有非常重要的地位。
分区表链存于硬盘上,一般由一个主引导结点和多个普通结点构成。主引导结点同PRI DOS分区对应,为硬盘的0柱面0头1扇区,是硬
盘主引导记录扇区。在头结点扇区中,从开始到0DAH的218 字节是一段主引导程序;从0DBH到1BDH共228字节为00H;从1BEH到1FDH处64字
节是硬盘的主分区表,共四个表项,每个表项16字节,其中前两个表项分别指示主分区和扩展分区在硬盘中的信息,后两个表项一般不用,
全为00H;;扇区最后两个字节是结束标志55H、AAH。
表项的数据结构如下:
相对偏移 长度(BYTE) 含义
0 1 激活标志
1 3 分区起始位置(柱、头、扇)
4 1 分区类型
5 3 分区终止位置(柱、头、扇)
8 4 分区起始扇区的相对序号
12 4 分区大小
表项结构中的激活标志在激活时为80H(否则为00H),所谓起始位置,对于本分区表项而言,是该分区的起始柱1头1扇区;对于扩展
表项而言指的是相应的扩展分区的起始柱0头1扇区。分区类型常见值有1、4、6、5等。1表示12位FAT的分区,4表示16位FAT的分区,6 表
示容量大于32M的分区,5表示扩展分区。分区大小等于各相应分区从起始扇区到终止扇区的扇区数,对于本分区表项,此值不含隐含扇区,
对于扩展表项此值包含隐含扇区,而对PRI DOS 分区里的扩展表项,此值等于各逻辑分区所有扇区包括隐含扇区之和。所谓起始扇区的相
对应序号,其相对起点分三种情况:对于本分区表项,序号是相对于该分区的起始柱0头1扇区;对于扩展表项,若是PRI DOS的扩展分区,
则相对于PRI DOS分区的主引导记录扇区;若是逻辑分区的扩展, 则一律相对于整个扩展分区的起点,此起点一般就是第一逻辑分区的起
始柱0头1扇区。
三、建立多个PRI DOS分区
从上面的分析中我们清楚了分区表由四个表项组成(尽管一般最多只使用两项),并且主分区表的第一表项指向PRI DOS分区,第二个
表项指向扩展分区。如果按照正常的使用方法,完全没有必要设置四个表项,既然如此设置,必有其使用的目的。由于主分区表中的扩展
表项中的某些项包含了所有扩展分区的有关信息,为此我先用 FDISK建立只有一个逻辑分区的扩展分区。然后将该扩展分区表项的分区类
型由5改为6,再将其激活标志由00H改为80H(注意必须同时将原先的PRI DOS分区的激活标志由80H改为00H)。 然后必须重新用软盘启动
机器并格式化C盘,则就可用新建立的PRI DOS分区启动机器( 原先的PRI DOS分区的盘符变为D)。这样就建立了两个PRI DOS分区。
四、隐含分区的设置和恢复
我们已经知道硬盘主引导记录扇区中从0DBH到1BDH共228 个字节为00H,在建立了多个PRI DOS分区之后,就可利用这228 个字节的最
后64个字节来保存四个表项有内容。选定一个PRI DOS分区, 然后将四个表项中的其它所有分区类型为非扩展分区的表项的内容全部改为
00H。这样在硬盘上就只有一个PRI DOS分区,其它被隐含起来。
如要将隐含分区恢复正常,只需将其保存在主硬盘主引导扇区中的内容重新写入到该表项即可。
五、源程序
下面给出源程序:PDOS.CPP。该源程序在编译环境TURBOC++ 3.0下在兼容机上编译。使用方法为在DOS提示符下键入:[D:] [ PATH]
PDOS <C/S/R/1/2/3/4>(S:建立PRI DOS分区;S:对PRI DOS分区表项进行备份;R:收复PRI DOS分区表项;1:只保留PRI DOS分区表项的第
一项,其余均隐含;2:只保留PRI DOS分区表项的第二项;3: 只保留PRI DOS分区表项的第三项;4:只保留PRI DOS分区表项的最后一项)。
以下为PDOS.CPP程序清单:
#include<dos.h>
#include<bios.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
struct HSC
{char hd,sc,cy;};
struct PartitionTable
{char Flag; /* 激活标志 */
HSC begin; /* 开始位置 */
char TYpe; /* 分区类型 */
HSC end; /* 结束位置 */
long id; /* 开始扇区的相对序号 */
long size; /* 分区大小 */
};
struct note /* 结点结构 */
{char boot1[366];
PartitionTable PT[1];
PartitionTable PT1[4];
PartitionTable PT2[4]; /* 主DOS分区表项 */
char f[2];
}dosboot;
void create_pri_dos(); /* 建立(将扩展分区修改成)主DOS分区 */
void set_hidde_dos(); /* 对主DOS分区表项进行备份 */
void recall_dos(); /* 恢复主DOS分区表项 */
void change_dos(char n); /* 只保留一个主DOS分区,其余均隐含 */
main(int argc,char *argv[])
{
char n;
if (argc!=2)
{ printf(\"Bad connamd !\");
return 0;
};
strlwr(argv[1]); /* 将参数中的大写字母转换成小写字母 */
while((*(argv[1]++))==0); /* 搜寻第一个非空格字符 */
n=*(--argv[1]);
switch(n){
case \'c\':
create_pri_dos();
break;
case \'s\':
set_hidde_dos();
break;
case \'r\':
recall_dos();
break;
case \'1\': /* 只保留主DOS分区表项中的第一项,其余主DOS分区表项均隐含 */
[NextPage]
change_dos(n);
break;
case \'2\': /* 只保留主DOS分区表项中的第二项 */
change_dos(n);
break;
case \'3\': /* 只保留主DOS分区表项上的第三项 */
change_dos(n);
break;
case \'4\': /* 只保留主DOS分区表项上的第四项 */
change_dos(n);
break;
default:
return 0;
};
return 0;
}
void create_pri_dos()
{int i;
biosdisk(2,0x80,0,0,1,1,&dosboot);
for (i=0;i<4;i++)
{if ((dosboot.PT2[i].TYpe!=0)&&(dosboot.PT2[i].TYpe!=5))
{dosboot.PT2[i].Flag=0x00;};
if (dosboot.PT2[i].TYpe==5)
{dosboot.PT2[i].TYpe=6;
dosboot.PT2[i].Flag=0x80;};
};
biosdisk(3,0x80,0,0,1,1,&dosboot);
return;
};
void set_hidde_dos()
{
int i;
biosdisk(2,0x80,0,0,1,1,&dosboot);
for(i=0;i<4;i++)
{if ((dosboot.PT2[i].TYpe!=0)&&(dosboot.PT2[i].TYpe!=5))
{dosboot.PT1[i]=dosboot.PT2[i];};
};
biosdisk(3,0x80,0,0,1,1,&dosboot);
return;
};
void recall_dos()
{
int i;
biosdisk(2,0x80,0,0,1,1,&dosboot);
for (i=0;i<4;i++)
{if (dosboot.PT1[i].TYpe!=\'0\')
{
dosboot.PT2[i]=dosboot.PT1[i];
dosboot.PT1[i]=dosboot.PT[0];
};
};
biosdisk(3,0x80,0,0,1,1,&dosboot);
return;
};
void change_dos(char n)
{
int i,m;
m=n-49;
biosdisk(2,0x80,0,0,1,1,&dosboot);
if (dosboot.PT1[m].TYpe!=0)
{ for (i=0;i<4;i++)
{if (dosboot.PT1[i].TYpe!=0)
{dosboot.PT2[i]=dosboot.PT[0];};
};
dosboot.PT2[m]=dosboot.PT1[m];
dosboot.PT2[m].Flag=0x80;
};
biosdisk(3,0x80,0,0,1,1,&dosboot);
return;
};
六、举例及注意事项
在1.2G的硬盘上建立三个PRI DOS分区,大小分别为300Mb, 400M和500MB的例子:
首先用FDISK建立一个300MB的PRI DOS分区和400MB的扩展分区,并激活PRI DOS分区,用软盘启动计算机并格式化C盘,执行PDOS S命
令,使扩展分区变成PRI DOS分区,再用软盘启动计算机并格式化C盘,原先的PRI DOS分区的盘符变为D。然后用FDISK建立500MB的扩展分区,
在执行PDOS S命令后,再用软盘启动计算机并格式化C盘, 这样就建立了三个PRI DOS分区。其盘符和容量的对应关系为C:500MB; D :
300MB;E:400MB。
由于在PRI DOS 分区表项之间切换时只保留一个表项可供使用,因此必须将PDOS.EXE程序拷贝到所有PRI DOS分区中。 另个读者在应
用本程序时一定要准确无误地输入源程序,以防破坏硬盘上的数据。