Windows NT Lab 8 - Memory-Mapped files

Lab Assignment

In this Lab Assignment, you are to create four three processes, similar to Lab 5. They will be source, encrypt, decrypt and sink. Their operation will be similar as in Lab 5, but they will use different mechanism for IPC. Sink will read an input text file and send each character to the encrypt process using Memory-Mapped files. Encrypt will perform encryption (say, by increasing character’s ASCII value by 1) and send the encrypted character to the Decrypt process using named pipes (if one experiences difficulties using named pipes, memory-mapped file can be used in this part as well). Decrypt process will retrieve the sent character and decrypt it (decreasing its ASCII value by 1) and it will then sent it to the sink process using memory-mapped file. Sink process will finally write it to the output file whose filename differs from the input filename.

Note: All three processes shall be run in their own console (CREATE_NEW_CONSOLE option during CreateProcess() function call) and should display what is occurring during their execution (for example, filter should display which character it read, to what it was converted, etc.) In other words, programs should have enough output to demonstrate their correct operation. Further, if you are making encryption by increasing ASCII value by 1, make sure you are still in the printable range (by using wraparound) when ASCII value is increased for the last alphabetical printable character.

Introduction

When more than two threads are running in a same process, or when a process starts more than two threads both threads are running in the process space of the same process; that means that both the threads can share the same information. For example parent process declares a variable ‘V1’ and creates two threads T1 and T2, then both T1 and T2 can access V1 and change it’s value. But when two threads belong to two different processes they cannot share any information. For this purpose we used pipes (Lab 5) and sockets (Lab 6) earlier and there are some more techniques through which we can make two threads communicate. Among all the techniques Memory-Mapped files are the most preferred one in Windows NT and are implemented in the lower level which makes them the fastest of them all.

Conceptually memory-mapped file is a disk-based file that is loaded into the primary memory. The OS can read and write into this file in a way that is very similar to reading and writing from an ordinary file (like the once you have been using to read and write information for your programming assignments: a txt file, for example).

However, there is one big difference in memory-mapped file and ordinary file. Unlike ordinary file a memory-mapped file can be accessed by two process at the same time, this is done by mapping the file into their address spaces. There is one small problem here, memory-mapped file are not protected against critical section problem. You have to use the regular locking mechanism, mutex and semaphore ex., for managing the critical section yourself.

Three steps to use memory-mapped files :

·  Obtain a handle to the file by creating or opening it ( equivalent to statement ifstream in(“in.txt”) when you would open an ordinary file in C++ )

·  Reserve virtual address space for the file.

·  Establish a mapping between the file and your virtual address space.

A file handle is obtained using CreateFile or OpenFile. The CreateFile function is discussed in Lab-5. when it is used with memory-mapped files, the normal parameters are used to create/open the file.

After a file has been opened, a file-mapping object stores the mapping information. It is created with CreaFileMapping, as follows.

HANDLE CreateFileMapping(

HANDLE hfile,

LPSECURITY_ATTRIBUTE

lpFileMappingAttributes,

DWORD flProtect,

DWORD dwMaximumSizeHigh,

DWORD dwMaximumSizeLow,

LPCSTR lpName );

The mapping object may use a name, lpName, or use NULL.

NOTE: If lpName is NULL, the mapping object is created without a name and cannot normally be shared. If lpName is defined and already exists, this request is to use the existing named mapping object. If lpName is defined but does not exit, it is created.

Once the mapping object has been created, the address space will have been established, though the file contents will not have actually been mapped to the process’s address space. This is accomplished using the following function:

LPVOID MapViewOfFile(

HANDLE hFileMappingObject,

DWORD dwDesiredAccess,

DWORD dwfileoffsetHigh,

DWORD dwfileoffsetLow,

DWORD dwNumberOfBytesToMap

);