操作系统实验:读/写磁盘指定位置信息

实验十一:读/写磁盘指定位置信息


一、实验目的

(1).了解磁盘的物理知识。
(2).掌握Windows系统提供的有关对磁盘操作API。
(3).根据输入的扇区号读/写指定扇区。

二、实验准备

注意:
	本实验要使用的主要数据结构DISK_GEOMETRY 是由系统提供的,其声明在#include “winioctl.h”中,因此要将其加入到实验程序的头文件说明中,否则程序编译时系统将无法识别DISK_GEOMETRY结构。

1.设置读/写操作的位置--SetFilePointer()函数
作用:
	用于移动一个打开文件中的读/写指针,这里磁盘设备被当作文件处理,因此用于移动文件读/写指针在磁盘上的位置。
原型:
DWORD  SetFilePointer(
    HANDLE  hFile,
	LONG    lpdistanceToMove,
    PLONG   lpDistanceToMoveHigh,
    DWORD   dwMoveMethod
);
参数说明:
hFile:打开的文件句柄,创建的文件必须具有GENERIC_READ或GENERIC_WRITE的存取权限。
lpDistanceToMove:指针要移动的偏移量的低32位,用于指定移动文件指针的字节大小。如果参数				lpDistanceToMoveHigh不为空,lpDistanceToMoveHigh和lpDistanceToMove两个参数形成一个64位的值	  来指定移动的位置。如果参数lpDistanceToMoveHigh为空,lpDistanceToMove是一个32位带符号值,当		lpDistanceToMove为正值时,文件指针向前移动,否则向后移动。
lpDistanceToMoveHigh:指针要移动的偏移量的高32位。如果不需要该参数,可以将其设置为空。当该参数不为空		时,该参数为文件指针的高32位的DWORD类型值。
dwMoveMethod:文件指针移动的初始位置
返回值:
  如果函数调用成功,而且参数lpDistanceToMoveHigh为空,返回值为文件指针的低32位DWORD类型值。如果参数lpdistanceToMoveHigh不为空,返回值为文件指针的低32位DWORD类型值,并且高32位DWORD类型值输出到一个long类型的参数中。
  如果函数调用失败,而且参数lpdistanceToMoveHigh不为空,返回值为0XFFFFFFFF,若要得到错误信息,请调用函数GetLastError()。如果函数调用失败,而且参数lpdistanceToMoveHigh不为空,返回值为0XFFFFFFFF,但由于0XFFFFFFFF不是一个有效的低32位DWORD类型值,必须通过调用函数GetLastError()才能判断是否有错误发生。若发生错误,则函数GetLastError()返回错误值,NO_ERROR否则返回。
如果新的文件指针位置是一个负值,则表明函数调用失败,文件指针将不移动,通过调用函数GetLastError()返回的值是ERROR_NEGATIVE_SEEK。

2.读文件--ReadFile()函数
原型:
BOOL ReadFile(
	HANDLE   hFile,                     //要读的文件的句柄
	LPVOID    lpBuffer,                 //指向文件缓冲区的指针
	DWORD   nNumberOfBytesToRead,    //从文件中要读取的字节数
	LPDWORD  pNumberOfBytesRead,   //指向要读取的字节数的指针	
	LPOVERLAPPED  lpOverlapped	     //指向OVERLAPPED结构的指针
);
3.写文件--WriteFile()函数
原型:
BOOL WriteFile(
	HANDLE  hFile,               //要读的文件的句柄
	LPVOID   lpBuffer,             //指向文件缓冲区的指针
	DWORD  nNumberOfBytesToWrite,      //从文件中要读取的字节数
	LPDWORD  lpNumberOfBytesWrite,     //指向要读取的字节数的指针
	LPOVERLAPPED  lpOverlapped	       //指向OVERLAPPED结构的指针
);

三、实验内容

(一)实验内容
在实验十的基础上,继续完成该实验。编写两个函数,分别完成如下功能。
	1.对给定的扇区号读取该扇区的内容。
	2.将用户输入的数据写入指定的扇区。
(二)主要代码
// 011.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "011.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();
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();

	while(TRUE)
	{
		printf("Please Select Read or Write!Input 'R' ro 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 device[]="\\\\.\\C:";
	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 ! \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("\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!\n");
	
	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,SecterMove;
	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("%d",&SectorNumber);
	printf("\n");
	Sector=disk_info.Cylinders.QuadPart*
		disk_info.TracksPerCylinder*
		disk_info.SectorsPerTrack;
	if (SectorNumber>Sector) printf("There is not this Sector!\n");
	printf("Please Input the Content to Write to Disk A:\n");
	scanf("%s",&WriteBuffer);
	SecterMove=SectorNumber*(disk_info.BytesPerSector);
	rc=SetFilePointer(Handle,SecterMove,NULL,FILE_BEGIN);	
	if (!WriteFile(Handle,WriteBuffer,512,&BytestoWrite,NULL))
	{
		printf("Read File Error:%d\n", GetLastError());
		return FALSE;
	}
	printf("Write Complete!\n");
	return TRUE;
}

四、实验结果与总结

	通过实验深入理解了操作系统将设备当作文件处理的特性,理解了函数SetFilePointer()、Readfile()及Writefile()中每个参数的实际意义并能在本实验中正确使用。
	在主程序中让用户选择:R、W或Q,若用户选择R,则调用函数BOOL SectorRead(HANDLE Handle),完成读给定扇区的功能;若用户选择W则调用函数BOOL SectorWrite(HANDLE Handle)完成对给定扇区号写入信息的功能;若用户选择Q,则程序退出。
读操作:

images

写操作:

images

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司马道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值