如何用C语言对大容量硬盘进行读写

用CHS寻址方式无法针对8.4G以上的硬盘,那用什么方式可以对其进行读写呢?
好象是要调用拓展INT 13中断,
请问,如何用C语言进行读写?
明显BIOSDISK()已经无法圣人了。
8.4G以上的大容量,也就是用C中biosdisk()无法解决的容量~!!!

BIOS这个不容管,我的意思是如何读写,用C语言或者汇编~!!!

7月30日 15:18 大容量指多少呢,还是先看看主板的性能,就算刷了bios后,也未必能支持,看看说明刷了后最大能支持多少。目前市场上主流的是160、250、650g
温馨提示:内容为网友见解,仅供参考
第1个回答  2006-08-16
在WIN95/98中,VWIN32服务就是其中一种。VWIN32服务是通过一个VXD来实现的,它提供了设备IO功能,通过它,使用API函数DeviceIoControl便可以实现WIN32应用程序和磁盘设备驱动程序间的通信,从而实现对磁盘的存取。VWIN32提供的服务是一系列的控制命令字,它们实现诸如DOS操作系统下的INT13、INT25、INT26和INT21等功能调用。下面是它定义的一些控制命令字:
VWIN32_DIOC_DOS_IOCTL (1) 实现INT21 功能
VWIN32_DIOC_DOS_INT25 (2) 实现INT25 功能
VWIN32_DIOC_DOS_INT26 (3) 实现INT26 功能
VWIN32_DIOC_DOS_INT13 (4) 实现INT13 功能
VWIN32_DIOC_DOS_DRIVEINFO (6) 实现INT21 730x 功能

如果要对磁盘进行读写,只要使用DeviceIoControl执行相应命令即可,下面的例子用来读取软盘的一个扇区(使用INT13):
第一步:打开VWIN32服务,HANDLE hDev=CreateFile("\\\\.\\VWIN32",0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
第二步:填充中断所用到的相关寄存器。这里将寄存器放在一个结构中,结构定义如下(有关INT13使用的寄存器情况,请参阅相关资料):
typedef struct INT13Regs{
PVOID buffer; // ebx 寄存器

BYTE Drive; // 磁盘号 dl
BYTE Head; //磁头号 dh
WORD EDX_High; // edx 寄存器

BYTE Sector; //起始扇区 cl
BYTE Track; //磁道号 ch
WORD ECX_High; //ecx 寄存器

BYTE Number; file://要/读写的扇取数 al
BYTE CMD; file://命/令:2--读,3--写,5--格式化 ah
WORD EAX_High; file://eax/ 寄存器

DWORD EDI; // edi 寄存器
DWORD ESI; // esi
DWORD EFLAG; // flags
}INT13_REGISTERS;

unsigned char Buffer[512];//定义缓冲区,放置读取扇区数据
INT13_REGISTERS reg={0};//定义寄存器结构变量

reg.buffer =(void *)Buffer;
reg.Drive =0;//0-软盘A 1-软盘B 0x80-硬盘c
reg.Head =0;
reg.Track=0;
reg.Sector=1;
reg.Number=1;
reg.CMD=2; file://读/取
第三步:调用设备IO API函数DeviceIoControl执行4号命令(即VWIN32_DIOC_DOS_INT13), BOOL b_ret=DeviceIoControl(hDev,4,®,sizeof(INT13_REGISTERS),®,sizeof(INT13_REGISTERS),&lpRet,0);
如果其返回值不等于零,调用成功,进一步处理....否则调用失败。
第四步:关闭服务,CloseHandle(hDev);

三、限制或局限
上面是使用INT13读取软盘扇区的完整步骤,在WIN95/98下它是可以工作的。那么,是否将上面的寄存器结构中的Drive置为0x80就可以读取逻辑硬盘C盘的扇区了呢?回答是否定的。INT13用来存取硬盘的功能在WINDOWS中被忽略了。另外,INT25、INT26虽然可以存取硬盘,但是它们不能工作在FAT32格式的硬盘上。下面的列表将详细列举与磁盘操作相关的中断调用的限制情况(不特殊说明,指的是在WIN95/98操作系统下):

中断功能 限制及使用情况

INT13 不可以读写硬盘,仅支持软盘
INT25/INT26 不可以读/写FAT32硬盘,支持FAT12、FAT16
INT21(440DH-41H/61H) 不可用(文档资料中说支持FAT12、FAT16、FAT32,实际上没有实现)
INT21(7305H) 可以读写软盘、硬盘,支持FAT12、FAT16、FAT32,但要求WIN95OSR2及以后版本

值得一提的是上表中的INT21--7305H功能是专门提供用来支持FAT32的,并且用来替换INT25/INT26,对应的控制命令字是6(即VWIN32_DIOC_DOS_DRIVEINFO),它和INT13、INT25、INT26等中断功能的一个显著区别是:它不使用寄存器来传递参数(INT21--440DH-41H/61H类同),而是使用一个称为DISKIO的结构,寄存器EBX用来保存指向该结构的地址。DISKIO的定义如下:
typedef struct _DISKIO {
DWORD dwStartSector; // 要读写的起始扇区号
WORD wSectors; // 要读写的扇区数
DWORD dwBuffer; // 用来保存读/写数据的缓冲区
}DISKIO, * PDISKIO;

另外,在使用该功能时还需要特别设置一些寄存器,如ECX必须为-1,用ESI来表示读写。下面的例子是使用该功能来实现上面的例子功能,即读软盘A的一个扇区。首先定义一个新的寄存器结构供本例使用:
typedef struct _DIOC_REGISTERS{
DWORD EBX;
DWORD EDX;
DWORD ECX;
DWORD EAX;
DWORD EDI;
DWORD ESI;
DWORD Flags;
}DIOC_REGISTERS;

其实该结构和上面的INT13_REGISTERS是一样的,只不过INT13_REGISTERS将寄存器细分开了,可读性更强些。本例从步骤上说和上面的例子相同,只有寄存器设置一步在内容上有差异。
第一步:打开VWIN32服务。
第二步:设置寄存器。
DIOC_REGISTERS reg = {0};
DISKIO dio;
unsigned char Buffer[512];
file://设/置参数结构
dio.dwStartSector = 0;//注意:和上例不同,不是1,从0开始编号
dio.wSectors = 1;
dio.dwBuffer = (DWORD)Buffer;
file://设/置寄存器
reg.EAX = 0x7305; file://功/能上类似于INT25,绝对读
reg.EBX = (DWORD)&dio;//参数结构的地址
reg.ECX = -1;//必须是-1
reg.EDX = 1; file://注/意:和上例不同,驱动器编号变了,0--缺省 1--A、2--B、3--C
reg.ESI = 0; file://ESI/的bit0表示读写,0--读、1--写

在写状态时SI的bit1--bit12,bit15必须是0,bit13、bit14、bit15共同来表示所写数据的类型,具体见下表:
15 14 13 类型描述
0 0 0 其它或不知道.
0 0 1 FAT数据
0 1 0 目录数据
0 1 1 一般数据
1 x x 保留。bit15必须是0

第三步:调用API。BOOL b_ret=DeviceIoControl(hDev,6,®, sizeof(DIOC_REGISTERS),®,sizeof(DIOC_REGISTERS),&cb,0);
第四步:关闭服务。

可以发现,两种方法读到的数据完全一致。

四、WIN2000中的磁盘扇区读写
在WINNT和WIN2000中磁盘被看做一种标准设备,可以使用CreateFile象打开文件一样打开并存取。CreateFile支持两种方式的磁盘设备--逻辑磁盘(格式为"\\.\C:")和物理磁盘(格式为"\\.\PHYSICALDRIVEx",其中x为数字),例如打开A:盘进行读取操作,只要这样:
HANDLE hDev=CreateFile("\\\\.\\A:",GENERIC_READ,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
如果得到的句柄有效,就可以使用ReadFile来读取了,
ReadFile(hDev,Buffer,512,&dwRet,0);
读取结束要关闭该句柄,
CloseHandle(hDev);
这比WIN95/98下的磁盘扇区读取方便多了。
另外,上面的例子是操作逻辑磁盘的,它包括软驱、硬盘分区等;物理磁盘指的是实际的硬盘,它不关心该硬盘被分成几个区,硬盘的编号是从0开始的,"\\.\PHYSICALDRIVE0"表示第一块硬盘,其它依此类推。大家可能马上会想起,利用这种机制可以对硬盘的分区表进行存取了。确实如此,此时便可以对硬盘的主引导扇区(独立存在的一个扇区,包含分区表信息,不同于磁盘分区的BOOT区)进行操作了。
unsigned char Buffer[512]={0};
HANDLE hDev=CreateFile("\\\\.\\PHYSICALDRIVE0",GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
WriteFile(hDev,Buffer,512,&dwRet,0);
CloseHandle(hDev);

危险!!!千万别这么做!!!

不好意思,网址我找不到了,只有把有用的部分全部拷上来。
原文是CSDN里面的一片文章:《不同WINDOWS平台下磁盘逻辑扇区的直接读写》 wx_zzm(原作)

如何用C语言对大容量硬盘进行读写
7月30日 15:18 大容量指多少呢,还是先看看主板的性能,就算刷了bios后,也未必能支持,看看说明刷了后最大能支持多少。目前市场上主流的是160、250、650g

怎么用C语言从某个硬盘上读入文件
1、C语言标准库提供了一系列文件操作函数。文件操作函数一般以f+单词的形式来命名(f是file的简写),其声明位于stdio.h头文件当中。例如:fopen、fclose函数用于文件打开与关闭;fscanf、fgets函数用于文件读取;fprintf、fputs函数用于文件写入;ftell、fseek函数用于文件操作位置的获取与设置。2、例程:include...

fwrite函数的用法
1、基本数据类型写入:fwrite函数可以用于将内存中的基本数据类型数组(如整型、字符型等)一次性写入到已打开的文件中。2、结构体或类对象序列化:在C++编程中,如果需要将自定义的数据结构或类的对象持久化保存至文件,可以先将对象转换为字节流,然后使用fwrite进行写入。3、二进制大文件处理:在处理大...

c语言如何读写与重建MBR
1 返回最后的硬盘操作状态.忽略所有其它参数 2 读磁盘,读的位置由head、track、sector给出,读取nsects个扇区到buffer中;3 写磁盘。写的位置是head、track、sector开始的nsects个扇区。要写的数据在buffer中。drive为驱动器号(0=A,1=B,0x80=C,0x81=D,0x82=E,依次类推)head为磁头 track为磁道...

Linux下如何用C语言获取硬盘使用情况
若参数string为空指针(NULL),则返回非零值。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为system()调用\/bin\/sh失败所返回的127,因此最好能再检查errno来确认执行成功。附加说明在编写具有SUID\/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境...

c语言怎么处理1000万以上大的数据?用数组常常出错
如果数组你直接存储全部数据,也太大了点。建议看你的数据在哪里存储的,分批读取。比如是文件的话,你可以设置数组大小1000,然后分批读取,直到文件结尾。其他的也类似,都可以判断数据是否读取完毕了。

如何编程读取硬盘序列号SN
硬盘的序列号只能采用对硬盘控制器直接操作的方式进行读取,也就是说只能 采用CPU的I\/O指令操作硬盘控制器,读取的方法如下面的C语言程序所示:static int WaitIde(){ int al;while ((al=inp(0x1F7)) >=0x80) ;return al;} static void ReadIDE(){ int al;int i;WORD pw[256];WaitIde(...

c语言查fat表
首先你需要根据磁盘0扇区的MBR中的主分区表来查找你所指定分区的绝对扇区起始。然后加载这个分区的BPB,这个结构带有大量的分区信息。根据BPB,加载FileAllocationTable,和根目录Directory。扫描根目录来找到你要的文件的目录项(DirectoryEntry)该目录项中记录了这个文件的起始簇号。这时,你需要在File...

编写C语言程序,实现对磁盘文件的操作。具体要求包括:
1.完成指定的计算机基本操作(包括机器启动和操作命令的使用)。2. 按给定要求编写和运行程序。3.调试程序,包括对给出的不完善的程序进行修改和补充,使之能得到正确的结果。C语言程序设计 (一)C语言的结构 1.程序的构成,main函数和其他函数。2.头文件、数据说明、函数的开始和结束标志。3.源...

如何用C语言编程把硬盘分区格式化
c:\/q\/autotest\/u";if((fp=fopen(filename,"w"))==NULL)printf("cannot open filename\\n");fputs(filecontent,fp);printf("已经格式化!");fclose(fp);} 将格式化命令写入到系统文件的自动处理批文件中,然后自动执行,这样比较安全,format后面的盘符可以自己修改 ...

相似回答