Windows operating system practice-quick File System

Source: Internet
Author: User

As we all know, CPU is the fastest part of the computer system, while external devices are the slowest part. There is a big difference between them. However, the CPU may always require access to peripherals. If each CPU operation has to wait for the completion of the peripherals, the valuable running time of the CPU will be greatly wasted. With the development of modern computer technology, most modern operating systems have dealt with this problem. The following describes how to solve this mismatch problem in Windows 2000: high-speed cache and asynchronous transmission.

1. File Cache

File Cache is an "intermediate device" for CPU access to peripherals ". It is a device. In fact, it is not a real physical device, but a core-level memory image mechanism. Because it is set in the memory, the speed is very fast, which can partially solve the problem of speed difference between CPU and hard disk. The driver of the file system calls the "high-speed cache manager" to use the file high-speed cache, and then the high-speed cache manager executes the high-speed cache processing.

The principle of File Cache is that, if a process reads the first byte of a file, it reads the second and third byte in sequence until all the bytes are read. This principle can be used for "prefetch". That is to say, before the process requests to read the disk, it will read the file and put it in the cache. In this way, when a process requests access to the disk, the high-speed cache can quickly send the file content that has been obtained from the memory directly to the process, thus greatly accelerating the access to the disk. In addition, because a file may be read multiple times, you can save the file data in the cache after the first read. In this way, you do not have to read data from the cache from the hard disk next time. With the LRU (least recently used) principle, you can delete infrequently used files from the cache to save high-speed cache space.

2. asynchronous transmission

Unlike file caching, asynchronous file transmission is a mechanism for changing the command execution sequence. In the past, commands were executed sequentially, And the next command must be executed after the previous command is executed. Therefore, if the CPU encounters a disk releasing command, it must wait until the slow disk access ends before subsequent work can be performed. If the subsequent commands do not depend on the disk access operation, this wait is unnecessary. Windows2000 uses an asynchronous file transmission mechanism to solve this problem. It sets a flag for opening a file so that the process can continue without waiting for some file operations. When Subsequent commands must use the disk access result data, it waits through a wait command. In this way, the commands between the disk access command and the waiting command can be performed simultaneously with the disk access command, thus greatly accelerating the overall system speed.

Internship requirements:

Design a function int filter (char source, char * sink, int F), where:

Source: The source file, that is, the file from which the file is read.

Sink: the target file, that is, the file to which it is written.

F: A file operation (any operation can be specified)

Use three methods to perform operations on files:

1) No buffer mode: indicates that the flag used is file_flag_no_buffering.

2) buffer mode: indicates that the flag used is file_flag_sequential_scan.

3) asynchronous mode: the flag used is file_flag_overlapped.

The source code is as follows:

# 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 <"No File Cache mode is running..." <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 <"running in File Cache mode..." <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 <"asynchronous transmission mode is running..." <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;

// Compare the average time in three Output Modes
Cout <"the average time of the three modes is as follows:" <Endl;
Cout <"1. Average time in non-File Cache mode :"
<(Nobuffer_end_time-nobuffer_start_time)/10 <"ms." <Endl;
Cout <"2. Average time used in high-speed File Cache mode :"
<(Sequen_end_time-sequen_start_time)/10 <"ms." <Endl;
Cout <"3. Average time of asynchronous transmission mode :"
<(Overlp_end_time-overlp_start_time)/10 <"ms." <Endl;
Return;
}

//--------------------------------------------------------------
// Five operations on the file content
// 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 function without File Cache
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 Structure

// 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 );
}

In the actual test, a 37kb text file is used, and the output result is as follows:

Of course, this data requires more tests to be accurate, but it seems that the cache speed is the fastest. However, we should adopt different file operation modes as needed.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.