操作系统实验十、获取磁盘基本信息

实验十:获取磁盘基本信息

一、实验目的

(1) 了解磁盘的物理组织。

(2) 熟悉Windows 系统如何查看磁盘相关系数。

(3) 掌握Windows 系统提供的有关对磁盘操作 API。

二、实验准备

1.相关系数数据结构说明

磁盘基本物理结构原型:

Typedef struct _DTSK_GEOMETRY {
    
    

    LARGE_INTEGER  Cylinders;

    MEDIA_TYPE MediaType;

    DWORD  TracksPerCylinder;

    DWORD  SectorsPerTrack;

    DWORD  BytesPerSector;

} DISK_GEOMETRY;

成员说明:

(1)Cylinders:磁盘的柱面数。

(2)MediaType:介质类型,如3.5英寸,1.44MB软盘。

(3)TracksPerCylinder :每个柱面的磁道数。

(4)SectorsPerTrack:每个磁道的扇区数。

(5)BytesPerSector:每个扇区的字节数。

2.相关API 函数介绍

(1)文件创建

函数CreateFile()用于打开磁盘驱动器并返回一个文件句柄,这里驱动器被当做文件来处理。有关文件操作函数的详细说明参见4.1.2节。

原型:

HANDLE CreateFile(

    LPCTSTE lpFileName,          //指向文件名的指针

    DWORD dwDesiredAccess,        //读/写访问模式

    DWORD dwShareMode,         //共享模式

    LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针

    DWORD dwCreateionaDisposition,      //文件存在标志

    DWORD dwFlagsAndAttributes,       //文件属性

    HANDLE hTemplateFile          //指向访问模板文件的句柄

);

(2)获取磁盘的基本信息

函数DeviceIoControl() 用于获取磁盘的基本信息

原型:

BOOL DeviceIoControl(

    HANDLE hDevice,            //设备句柄

    DWORD dwIoControlCode,        //操作控制代码

    LPVOID lpInBuffer,           //输入数据缓冲区

    DWORD nInBufferSize,          //输入数据缓冲区大小

    LPVOID lpOutBuffer,           //输出数据缓冲区

    DWORD nOutBufferSize,         //输出数据缓冲区大小

    LPDWORD lpBytesReturned,       //可获取的字节计数

    LPOVERLAPPED lpOverlapped,      //指向OVERLAPPED结构的指针

); 

参数说明:

1 hDevice: 目标设备的句柄,由CreateFile() 函数获得。

2 dwIoControlCode: 指定操作的控制信息,用该值可以辨别将要执行的操作,以及对哪类设备进行操作。该参数取值如表所示

dwIoControlCode 的值

描述
IOCTL_DISK_GET_DRIVE_GEOMETRY 得到磁盘物理结构信息
IOCTL_DISK_GET_PARTITION_INFO 得到磁盘分区信息
FSCTL_QUERY_FAT_BPB 返回FAT16或FAT12卷的前36字节
FSCTL_GET_COMPRESSION 获取文件或目录的压缩信息

3 lpInBuffer:指向一个缓冲区,该缓冲区存放指定操作所输入数据。

4 nInBufferSize:由lpInBuffer所指缓冲区大小。

5 lpOutBuffer:指向一个缓冲区,该缓冲区存放指定操作所输出数据。

6 nOutBufferSize:由lpOutBuffer所指缓冲区大小。

7 lpBytesReturned:实际输出结果所占字节数。

8 lpOverlapped:指向OVERLAPPED结构的指针。

返回值:

如果函数调用成功,则返回值为非0值。如果函数调用失败,则返回值为0。若要得到更多的错误信息,可调用函数GetLastError()。

三、实验内容

(一)实验内容

编写一个函数,根据给出的驱动器号读取磁盘基本信息,包括键盘的大小、该磁盘包括多少个扇区,该磁盘有多少个柱面,每个柱面的磁道数、每个磁道的扇区数、每个扇区包含的字节数。

(二)主要代码

// 11.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "11.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;
	char Choice;
	Handle=GetDiskInformation('A');

	while(TRUE)
	{
    
    
		printf("please Select Read or Write! Input‘R’ to read ,’W’ to write,’Q’ to quit!\n");
		Choice=getchar();
		printf("\n");
		switch(Choice)
		{
    
    
		case 'W':
			{
    
    
				if (!SectorWrite(Handle))
                    printf("Write Sector Fail!\n");
				getchar();
				break;
			}
		case 'R':
            {
    
    
                if(!SectorRead(Handle))   
                    printf("Read Sector Fail!\n");
                getchar();
                break;
            }
		case 'Q':
            {
    
    
                exit(0);
                break;
            }
            default:
            {
    
    
                printf("Input Error!,Try again please!\n");
                getchar();
            }
		}
	}
	return nRetCode;
}
HANDLE GetDiskInformation(char drivername)
{
    
    
	  char device[]="\\\\.\\:";
	  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_VALUE!");
	  if(GetLastError()==ERROR_ALREADY_EXISTS)
	   printf("Cannot 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("\t  BytesPerSector:  %d\n",disk_info.BytesPerSector);
		  printf("\t  SectorPerTrack:  %d\n",disk_info.SectorsPerTrack);
		  printf("\t  TracksPerCylinder:  %d\n",disk_info.TracksPerCylinder);
		  printf("\t  Cylinder:  %d\n",disk_info.Cylinders);
	  Sector=disk_info.Cylinders.QuadPart *disk_info.TracksPerCylinder *disk_info.SectorsPerTrack;
	  printf("\t There is %d Sectors! \n",Sector);
	  DiskSize=Sector *disk_info.BytesPerSector;
	  printf("\t Size of Disk: %4.2f KB\n",(DiskSize)/(1024*1024));
	  return FloopyDisk;

}
BOOL SectorRead(HANDLE Handle)
{
    
    
	char ReadBuffer[1024*16];
	DWORD SectorNumber;
	DWORD BytestoRead;
	DWORD Sector;
	DWORD rc;
	int i;
	if (Handle==NULL)
	{
    
    
	  printf ("There is No disk!\n");
	  return FALSE;
	}

	printf ("Please Input the Sector Number to Read From:\n");
	scanf("%d",&SectorNumber);
	printf ("\n");
	Sector =disk_info.Cylinders.QuadPart*
		disk_info.TracksPerCylinder*
		disk_info.SectorsPerTrack;
	if (SectorNumber>Sector) 
		printf("There is not this Sector !");
	printf("Content:\n");
	BytestoRead=SectorNumber*(disk_info.BytesPerSector);
	rc=SetFilePointer(Handle,BytestoRead,NULL,FILE_BEGIN);
	if (!ReadFile(Handle,ReadBuffer,BytestoRead,&BytestoRead,NULL))
	{
    
    
	  printf("Read File Error:%d\n",GetLastError());
	  return FALSE;
	}
	printf("\t Text Content:\n");
	for (i=0;i<512;i++)
	{
    
     
	  printf("%c",ReadBuffer[i]);
	}
	printf("\n");
	printf("\t  Hex Text Content: \n");
	for (i=0;i<512;i++)
	{
    
    
	  printf("%x",ReadBuffer[i]);
	  printf(" ");
	}
	printf("\n");
	return TRUE;
}
BOOL SectorWrite(HANDLE Handle)
{
    
    
    char WriteBuffer[1024];
    DWORD SectorNumber,SectorMove;
    DWORD BytestoWrite;
    DWORD Sector;
	DWORD rc;
    if(Handle ==NULL)
    {
    
    
        printf("There is no disk\n");
        return FALSE;
    }
    printf("Please Input the Sector Number to Write to\n");
    scanf("%s",&SectorNumber);
    printf("\n");
    Sector=disk_info.Cylinders.QuadPart* disk_info.TracksPerCylinder* disk_info.SectorsPerTrack;
    if(SectorNumber>Sector) 
        printf("There is no Sector! \n");
    printf("Please Input the Content to Write to Disk A: \n");
    scanf("%s",&WriteBuffer);
    SectorMove=SectorNumber*(disk_info.BytesPerSector);
    rc=SetFilePointer(Handle, SectorMove,NULL,FILE_BEGIN);
    if(!WriteFile(Handle,WriteBuffer,512,&BytestoWrite,NULL))
    {
    
    
            printf("Read File Error:%d \n",GetLasttoWrite,NULL);
            return FALSE;
    }
    printf("Write Complete!\n");
    return TRUE;
}

四、实验结果与总结

image

从实验结果可以看出,对给定的磁盘驱动器中的软件A,本实验能正确识别出它每个扇区有512字节,每个磁道有18个扇区,每个柱面有两个磁道,共有80个柱面,该盘共有2280个磁道,磁盘的大小是1.41MB。应当注意,磁道上有一部分空间是存储磁盘的物理信息的,这部分空间系统是不能够直接存取的,因此没有编入逻辑扇区,也就是说逻辑扇区比磁盘的实际扇区要小,因此计算出的磁盘大小是磁盘可用空间的大小,比磁盘的物理大小要小。

猜你喜欢

转载自blog.csdn.net/weixin_44775375/article/details/107754949
今日推荐