实验十:获取磁盘基本信息
一、实验目的
(1) 了解磁盘的物理组织。
(2) 熟悉Windows 系统如何查看磁盘相关系数。
(3) 掌握Windows 系统提供的有关对磁盘操作 API。
二、实验准备
磁盘基本物理结构原型:
Typedef struct_DTSK_GEOMETRY {
LARGE_INTEGER Cylinders; //磁盘的柱面数
MEDIA_TYPE MediaType; //介质类型,如3.5英寸,1.44MB软盘
DWORD TracksPerCylinder; //每个柱面的磁道数
DWORD SectorsPerTrack; //每个磁道的扇区数
DWORD BytesPerSector; //每个扇区的字节数
} DISK_GEOMETRY;
相关API函数:
1.文件创建:
函数CreateFile() 用于打开磁盘驱动器并返回一个文件句柄,这里驱动器被当做文件来处理。
原型:
HANDLE CreateFile(
LPCTSTE lpFileName, //指向文件名的指针
DWORD dwDesiredAccess, //读/写访问模式
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
DWORD dwCreateionaDisposition, //文件存在标志
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //指向访问模板文件的句柄
);
2.获取磁盘的基本信息:
函数DeviceIoControl() 用于获取磁盘的基本信息
原型:
BOOL DeviceIoControl(
HANDLE hDevice, //设备句柄,由CreateFile() 函数获得
DWORD dwIoControlCode, //操作控制代码
LPVOID lpInBuffer, //输入数据缓冲区
DWORD nInBufferSize, //输入数据缓冲区大小
LPVOID lpOutBuffer, //输出数据缓冲区
DWORD nOutBufferSize, //输出数据缓冲区大小
LPDWORD lpBytesReturned, //可获取的字节计数
LPOVERLAPPED lpOverlapped, //指向OVERLAPPED结构的指针
);
表 1 dwIoControlCode 的值
值 | 描述 |
---|---|
IOCTL_DISK_GET_DRIVE_GEOMETRY | 得到磁盘物理结构信息 |
IOCTL_DISK_GET_PARTITION_INFO | 得到磁盘分区信息 |
FSCTL_QUERY_FAT_BPB | 返回FAT16或FAT12卷的前36字节 |
FSCTL_GET_COMPRESSION | 获取文件或目录的压缩信息 |
返回值:
如果函数调用成功,则返回值为非0值。如果函数调用失败,则返回值为0。若要得到更多的错误信息,可调用函数GetLastError()。
三、实验内容
编写一个函数,根据给出的驱动器号读取磁盘基本信息,包括键盘的大小、该磁盘包括多少个扇区,该磁盘有多少个柱面,每个柱面的磁道数、每个磁道的扇区数、每个扇区包含的字节数。
四、实验要求
了解MSDNLibraryVisualStudio6.0中提供的磁盘主要数据结构DISK_GEOMETRY中每个成员的含义,深入理解操作系统将设备当做文件处理的特性,理解函数CreateFile()及DeviceIoControl()中每个参数的实际意义并能在本实验中正确使用。
五、实验结果
六、源代码
// Disk_Information.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Disk.h"
#include "winioctl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
DISK_GEOMETRY disk_info;
HANDLE GetDiskInformation(char drivername);
BOOL SectorRead(HANDLE Handle);
BOOL SectorWrite(HANDLE Handle);
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode=0;
HANDLE Handle;
Handle=GetDiskInformation('C');
return nRetCode;
}
HANDLE GetDiskInformation(char drivername)
{
char device[]="\\\\.\\C:";
device[4]=drivername;
HANDLE FloopyDisk;
DWORD ReturnSize;
DWORD Sector;
double DiskSize;
FloopyDisk=CreateFile(device,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_NO_BUFFERING,
NULL);
if(FloopyDisk==INVALID_HANDLE_VALUE)
printf("INVALID_HANDLE_VALVE!\n");
if(GetLastError()==ERROR_ALREADY_EXISTS)
printf("Can not Open Disk!%d\n",GetLastError());
if (!DeviceIoControl(FloopyDisk,IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&disk_info,
50,
&ReturnSize,
(LPOVERLAPPED)NULL))
printf("Open Disk Error!%d\n", GetLastError());
printf("Disk Information:\n");
printf("\tBytesPerSector:%d\n",disk_info.BytesPerSector);
printf("\tSectorPerTrack:%d\n",disk_info.SectorsPerTrack);
printf("\tTrackPerCylinder:%d\n",disk_info.TracksPerCylinder);
printf("\tCylinder: %d\n", disk_info.Cylinders);
Sector= disk_info. Cylinders.QuadPart* disk_info. TracksPerCylinder* disk_info. SectorsPerTrack;
printf("\tThere is %d Sectors!\n", Sector);
DiskSize=Sector*disk_info. BytesPerSector;
printf("\tSize of Disk: %4.2fMB\n",(DiskSize)/(1024*1024));
return FloopyDisk;
}
``
七:实验总结
从实验结果可以看出,对给定的磁盘驱动器中的C,本实验能正确识别出它每个扇区有512字节,每个磁道有63个扇区,每个柱面有255个磁道,共有124519个柱面,该盘共有2000397735个磁道,磁盘的大小是1908.71MB。应当注意,磁道上有一部分空间是存储磁盘的物理信息的,这部分空间系统是不能够直接存取的,因此没有编入逻辑扇区,也就是说逻辑扇区比磁盘的实际扇区要小,因此计算出的磁盘大小是磁盘可用空间的大小,比磁盘的物理大小要小。