Windows操作系统实习之快速文件系统

众所周知,CPU是整个计算机系统中运算速度最快的部分,而外部设备是最慢的部分,它们之间存在着很大的差别。然而,CPU却时时刻刻可能要求访问外设。如果CPU的每次操作都必须等待外设完成,那么CPU宝贵的运行时间就会大大浪费。随着现代计算机技术的发展,大多数现代操作系统都对这个问题进行了处理。下面就介绍Windows 2000中解决这个不匹配问题的方法:高速缓存和异步传输。

1.文件高速缓存

文件高速缓存是CPU访问外设的一个“中间设备”。说是设备,其实它不是真正的物理设备,而是一种核心级内存映像机制。由于它被设置在内存中,因此速度非常快,可以部分解决CPU与硬盘速度差异的问题。文件系统的驱动程序通过调用“高速缓存管理程序” 来使用文件高速缓存,然后高速缓存管理程序执行高速缓存的处理工作。

文件高速缓存的原理是:假设一个进程读了文件的第一个字节,它常常会按照顺序读第二个第三个字节,一直到读出所有的字节。利用这个原理可以进行“预取”,也就是说,在进程没请求读磁盘之前就先把文件读出来并放到高速缓存中。这样,当进程请求访问磁盘时,高速缓存可以快速地把已经取到内存中的文件内容直接送给进程使用,从而大大加速了访问磁盘的速度。另外,由于一个文件可能会被多次读入,因此可以在第一次读入后,将文件数据保存在高速缓存中。这样,下次再读时,就不必从硬盘而可以从缓存中读取。利用LRU(Least Recently Used)的原则,可以将不常使用的文件从缓存中删除以节省高速缓存空间。

2.异步传输

与文件高速缓存不同,文件的异步传输是一种改变指令执行顺序的机制。在以往的操作系统中,指令都是顺序执行的,下一条指令必须在上一条指令执行完毕后才能执行。因此,如果CPU遇到一条放盘指令,那么它就必须等待缓慢的磁盘访问结束以后才能进行后续工作。如果它后面遇到的指令并不依赖于访盘操作时,这个等待就很没有必要。Windows2000中使用了一种异步文件传输机制来解决这个问题。它通过设置打开文件时的一个标志位来使进程不等待读些文件操作而继续执行。当后续指令必须用到磁盘访问的结果数据时,它在通过一条Wait指令进行等待。这样,在访盘指令和等待指令之间的指令就可以与磁盘访问同时进行了,从而大大加快了系统的整体速度。

实习要求:

设计一个函数int filter(char source, char *sink, int f),其中:

source:源文件,即从哪个文件读。

sink:目标文件,即写到哪个文件。

f:一个对文件的操作(可以指定任何操作)

分别用3种方法实现一个对文件的操作:

1)无缓冲方式:表示用的标志位是FILE_FLAG_NO_BUFFERING。

2)缓冲方式:表示用的标志位是FILE_FLAG_SEQUENTIAL_SCAN。

3)异步方式:表示用的标志位是FILE_FLAG_OVERLAPPED。

源代码如下:

#include <iostream.h>
#include <windows.h>

// three partterns
void filter_nobuffer(char *source, char *sink, void (*func)(char *addr));
void filter_sequen(char *source, char *sink, void (*func)(char *addr));
void filter_overlp(char *source, char *sink, void (*func)(char *addr));

// five function operations
void f1(char *addr);
void f2(char *addr);
void f3(char *addr);
void f4(char *addr);
void f5(char *addr);

#define BUFFER_SIZE 1024
char *buffer;

void main()
{
 // allocate the buffer
 buffer = new char[BUFFER_SIZE];

 DWORD tick;

 DWORD nobuffer_average_time = 0;
 DWORD sequen_average_time = 0;
 DWORD overlp_average_time = 0;

 cout<<"无文件高速缓存模式正在运行..."<<endl;

 DWORD nobuffer_start_time = GetTickCount();

 tick = nobuffer_start_time;
 filter_nobuffer("source.txt", "nobuffer_1.txt", f1);
 cout<<"nobuffer 0-1: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_1.txt", "nobuffer_2.txt", f2);
 cout<<"nobuffer 1-2: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_2.txt", "nobuffer_3.txt", f3);
 cout<<"nobuffer 2-3: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_3.txt", "nobuffer_4.txt", f4);
 cout<<"nobuffer 3-4: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_4.txt", "nobuffer_5.txt", f5);
 cout<<"nobuffer 4-5: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_5.txt", "nobuffer_6.txt", f1);
 cout<<"nobuffer 5-6: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_6.txt", "nobuffer_7.txt", f2);
 cout<<"nobuffer 6-7: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_7.txt", "nobuffer_8.txt", f3);
 cout<<"nobuffer 7-8: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_8.txt", "nobuffer_9.txt", f4);
 cout<<"nobuffer 8-9: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_nobuffer("nobuffer_9.txt", "nobuffer_10.txt", f5);
 DWORD nobuffer_end_time = GetTickCount();
 cout<<"nobuffer 9-10: "<<nobuffer_end_time - tick<<" ms."<<endl;

 cout<<"使用文件高速缓存模式正在运行..."<<endl;

 DWORD sequen_start_time = GetTickCount();
 
 tick = sequen_start_time;
 filter_sequen("source.txt", "sequen_1.txt", f1);
 cout<<"sequen 0-1: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_1.txt", "sequen_2.txt", f2);
 cout<<"sequen 1-2: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_2.txt", "sequen_3.txt", f3);
 cout<<"sequen 2-3: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_3.txt", "sequen_4.txt", f4);
 cout<<"sequen 3-4: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_4.txt", "sequen_5.txt", f5);
 cout<<"sequen 4-5: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_5.txt", "sequen_6.txt", f1);
 cout<<"sequen 5-6: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_6.txt", "sequen_7.txt", f2);
 cout<<"sequen 6-7: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_7.txt", "sequen_8.txt", f3);
 cout<<"sequen 7-8: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_8.txt", "sequen_9.txt", f4);
 cout<<"sequen 8-9: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_sequen("sequen_9.txt", "sequen_10.txt", f5);
 DWORD sequen_end_time = GetTickCount();
 cout<<"sequen 9-10: "<<sequen_end_time - tick<<" ms."<<endl;

 cout<<"异步传输模式正在运行..."<<endl;

 DWORD overlp_start_time = GetTickCount();

 tick = overlp_start_time;
 filter_overlp("source.txt", "overlp_1.txt", f1);
 cout<<"overlp 0-1: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_1.txt", "overlp_2.txt", f2);
 cout<<"overlp 1-2: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_2.txt", "overlp_3.txt", f3);
 cout<<"overlp 2-3: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_3.txt", "overlp_4.txt", f4);
 cout<<"overlp 3-4: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_4.txt", "overlp_5.txt", f5);
 cout<<"overlp 4-5: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_5.txt", "overlp_6.txt", f1);
 cout<<"overlp 5-6: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_6.txt", "overlp_7.txt", f2);
 cout<<"overlp 6-7: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_7.txt", "overlp_8.txt", f3);
 cout<<"overlp 7-8: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_8.txt", "overlp_9.txt", f4);
 cout<<"overlp 8-9: "<<GetTickCount() - tick<<" ms."<<endl;

 tick = GetTickCount();
 filter_overlp("overlp_9.txt", "overlp_10.txt", f5);
 DWORD overlp_end_time = GetTickCount();
 cout<<"overlp 9-10: "<<overlp_end_time - tick<<" ms."<<endl;

 // 输出3种模式下的平均时间做对比
 cout<<"3种模式的平均用时如下:"<<endl;
 cout<<"1.无文件高速缓存模式平均用时:"
  <<(nobuffer_end_time - nobuffer_start_time)/10<<" ms."<<endl;
 cout<<"2.使用高速文件缓存模式平均用时:"
  <<(sequen_end_time - sequen_start_time)/10<<" ms."<<endl;
 cout<<"3.异步传输模式平均用时:"
  <<(overlp_end_time - overlp_start_time)/10<<" ms."<<endl;
 return;
}

// --------------------------------------------------------------
// 对文件内容进行的5种操作
// f1 +1
// f2 -1
// f3 *1
// f4 >>
// f5 <<
void f1(char *addr){ *addr = (unsigned char)*addr + 1;}
void f2(char *addr){ *addr = (unsigned char)*addr - 1;}
void f3(char *addr){ *addr = (unsigned char)*addr * 1;}
void f4(char *addr){ *addr = (unsigned char)*addr >> 1;}
void f5(char *addr){ *addr = (unsigned char)*addr << 1;}

// --------------------------------------------------------------

// 没有文件高速缓存的filter函数
void filter_nobuffer(char *source, char *sink, void (*func) (char *addr))
{
 HANDLE handle_src, handle_dst;  // handles of source file and destination file
 BOOL cycle;
 DWORD NumberOfBytesRead, NumberOfBytesWrite, index;

 // open the source file
 handle_src = CreateFile(source, GENERIC_READ, NULL, NULL,
  OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);

 handle_dst = CreateFile(sink, GENERIC_WRITE, NULL, NULL,
  CREATE_ALWAYS, NULL, NULL);

 if(handle_src == INVALID_HANDLE_VALUE || handle_dst == INVALID_HANDLE_VALUE)
 {
  cout<<"CreateFile Invocation Error!"<<endl;
  exit(1);
 }

 cycle = TRUE;
 // use cycle to know when we finished reading the file
 while(cycle)
 {
  // read data and send them into buffer from the source file
  if(ReadFile(handle_src, buffer, BUFFER_SIZE, &NumberOfBytesRead, NULL) == FALSE)
  {
   cout<<"ReadFile Error!"<<endl;
   exit(1);
  }

  if(NumberOfBytesRead < BUFFER_SIZE)
   cycle = FALSE;

  // do the operation to the file
  for(index = 0; index < NumberOfBytesRead; index ++)
   func(&buffer[index]);

  // write the content of the buffer to the destination file
  if(WriteFile(handle_dst, buffer, NumberOfBytesRead, &NumberOfBytesWrite, NULL) == FALSE)
  {
   cout<<"WriteFile Error!"<<endl;
   exit(1);
  }
 }

 // close the file handle
 CloseHandle(handle_src);
 CloseHandle(handle_dst);
}

void filter_sequen(char *source, char *sink, void (*func) (char *addr))
{
 HANDLE handle_src, handle_dst;  // handles of source file and destination file
 BOOL cycle;
 DWORD NumberOfBytesRead, NumberOfBytesWrite, index;

 // open the source file
 handle_src = CreateFile(source, GENERIC_READ, NULL, NULL,
  OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

 handle_dst = CreateFile(sink, GENERIC_WRITE, NULL, NULL,
  CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

 if(handle_src == INVALID_HANDLE_VALUE || handle_dst == INVALID_HANDLE_VALUE)
 {
  cout<<"CreateFile Invocation Error!"<<endl;
  exit(1);
 }

 cycle = TRUE;
 // use cycle to know when we finished reading the file
 while(cycle)
 {
  // read data and send them into buffer from the source file
  if(ReadFile(handle_src, buffer, BUFFER_SIZE, &NumberOfBytesRead, NULL) == FALSE)
  {
   cout<<"ReadFile Error!"<<endl;
   exit(1);
  }

  if(NumberOfBytesRead < BUFFER_SIZE)
   cycle = FALSE;

  // do the operation to the file
  for(index = 0; index < NumberOfBytesRead; index ++)
   func(&buffer[index]);

  // write the content of the buffer to the destination file
  if(WriteFile(handle_dst, buffer, NumberOfBytesRead, &NumberOfBytesWrite, NULL) == FALSE)
  {
   cout<<"WriteFile Error!"<<endl;
   exit(1);
  }
 }

 // close the file handle
 CloseHandle(handle_src);
 CloseHandle(handle_dst);
}

void filter_overlp(char *source, char *sink, void (*func) (char *addr))
{
 HANDLE handle_src, handle_dst;  // handles of source file and destination file
 BOOL cycle;
 DWORD NumberOfBytesRead, NumberOfBytesWrite, index, dwError;
 OVERLAPPED overlapped;    // overlapped 结构

 // open the source file
 handle_src = CreateFile(source, GENERIC_READ, NULL, NULL,
  OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);

 handle_dst = CreateFile(sink, GENERIC_WRITE, NULL, NULL,
  CREATE_ALWAYS, NULL, NULL);

 if(handle_src == INVALID_HANDLE_VALUE || handle_dst == INVALID_HANDLE_VALUE)
 {
  cout<<"CreateFile Invocation Error!"<<endl;
  exit(1);
 }

 // initialize the overlapped struct
 overlapped.hEvent = NULL;
 overlapped.Offset = -BUFFER_SIZE;
 overlapped.OffsetHigh = 0;

 cycle = TRUE;
 // use cycle to know when we finished reading the file
 while(cycle)
 {
  // calculate the offset of the file
  overlapped.Offset = overlapped.Offset + BUFFER_SIZE;

  // read data and send them into buffer from the source file
  if(ReadFile(handle_src, buffer, BUFFER_SIZE, &NumberOfBytesRead, &overlapped) == FALSE)
  {
   switch(dwError = GetLastError())
   {
   case ERROR_HANDLE_EOF:
    cycle = FALSE;
    break;
   case ERROR_IO_PENDING:
    if(GetOverlappedResult(handle_src, &overlapped, &NumberOfBytesRead, TRUE) == FALSE)
    {
     cout<<"GetOverlappedResult Error!"<<endl;
     exit(1);
    }
    break;
   default:
    break;
   }
  }

  if(NumberOfBytesRead < BUFFER_SIZE)
   cycle = FALSE;

  // do the operation to the file
  for(index = 0; index < NumberOfBytesRead; index ++)
   func(&buffer[index]);

  // write the content of the buffer to the destination file
  if(WriteFile(handle_dst, buffer, NumberOfBytesRead, &NumberOfBytesWrite, NULL) == FALSE)
  {
   cout<<"WriteFile Error!"<<endl;
   exit(1);
  }
 }

 // close the file handle
 CloseHandle(handle_src);
 CloseHandle(handle_dst);
}

实际测试当中,采用一个37KB的文本文件,输出结果如下:

当然,这些数据还需要更多的测试才准确,但是整体看来还是使用高速缓存时速度最快啊。不过我们还是应该根据情况采用不同的文件操作模式。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值