![]() |
Memory-Mapped files in OS/2Written by Sergey Yevtushenko |
ForewordThis article explain small library which implement memory-mapped files in OS/2.Overview of Memory-Mapped FilesMemory-mapped files is a technique used for accessing files like ordinary RAM. Frequently this method of accessing files is mentioned as one of the advantages of the APIs of some flawors of Unix or of Windows NT, but OS/2 is also capable of doing so, although this is not directly mentioned in API. Let me explain this statement: Accessing files like RAM can be done in two ways: load the file into memory and access memory instead of the file and use the virtual memory engine to load parts of file on indirect application demand. This first method is well known but requires large amounts of memory for large files, is slow, and of course it does not do direct mapping between memory and the file. The second method is much more interesting. It does not require having files loaded into memory and the mapping between the position in the file and memory address is direct. This technique is called "Memory Mapped File" or MMF. Because accessing files in this way requires the support of the virtual memory engine, you might imagine that this is required to be implemented in the OS/2 kernel, but this is not so. The OS/2 API provides all required lower level APIs to implement this method at the application level. Let's look at this technique. To implement this technique we need three things: the ability to allocate address space, the ability to change the status of some parts of the address space (map to real memory, i.e. "commit") and notification when we try to access this address space at points not yet committed. For the first two purposes the OS/2 API provides DosAllocMem and DosSetMem functions. The last thing required is an exception handling API. Step-by-step Implementation of Memory Mapped Files0. Install exception handler
The installation of the exception handler is done by the MMF library
function DosInitMMF. This function should be called before any other call
to the MMF library will be made. Because it requires a pointer to a
structure in the application stack (to be exact, this is a requirement of
DosSetExceptionHandler), it can't be called before main() using a portable
across compilers technique (for example using C++ static objects).
Therefore the beginning of main() should look like:
The rest of the steps are done inside the DosAllocMMF library function.
It returns a pointer to the allocated memory region and you can access
this memory directly. Furthermore: any library function which accepts a
pointer to memory will work without knowledge about the real source of
this memory. You may ask "where is trick?" Well, there is no trick at all:
the pointer returned by DosAllocMMF requires additional processing in
order that access to it will not cause a trap or reading of garbage. This
processing is delayed before this memory is really accessed and is done in
the exception handler installed by DosInitMMF. Because this is the most
interesting part of the library, we will look inside it for more details:
Comments make this piece of code almost self-explanatory, but two things should be noted. Exceptions which are not related to MMF will be filtered out and therefore can be handled by another exception handler. Also, opening files in read-only mode can be useful for accessing large amounts of static data. As you can see, this handler does most of the work of reading parts of the file on application demand. But it does not discard pages not accessed for long time. You can improve this implementation by adding this feature. Some rudimentary parts of this idea are already done: pages accessed only for reading are distinguished from pages accessed for write. Example Program/* ** Module :MMF_TEST.C ** Abstract :Memory mapped file API example ** ** Copyright (C) Sergey I. Yevtushenko ** Log: Wed 03/09/97 Created */ #include <mmf.h> #include <stdio.h> #include <string.h> int main(VOID) { MMFINIT RegRec = {0,0}; char * data; char * data2; int rc; DosInitMMF(&RegRec); rc = DosAllocMMF("datafile", (void **)&data, MMF_READWRITE); printf("rc = %d\n", rc); /* Try to uncomment these lines in any order and compare program output and 'datafile' */ printf("Data: %s\n", data); /* data[4096] = ''; */ /* printf("Data: %s\n", data); */ /* ATTENTION !!! Uncommenting following line will update file 'datafile' */ /* DosUpdateMMF(data); */ DosFreeMMF(data); return 0; } This example opens "datafile" for reading and writing and prints the contents of the file using printf. To become more familiar with MMF, you can do some experiments with this code by uncommenting some commented-out lines. Before trying this example don't forget to create a file named "datafile" filled with, for example, text, and be sure to make it long enough (5K or so). General Considerations for Using Memory Mapped FilesAt first you should note that massive access to files with this technique is not recomended. It reads files by 4K pages. In some cases this size is too small to be effective. Much more appropriate is accessing large files of which only a small portion is actually read into memory. An example of appropriate use of MMF is the file viewer built into the ZTreeBold file manager written by Kim Henkel. Final WordsThe implementation of memory mapped files in OS/2 has some advantages and some disadvantages. One advantage is the complete flexibility of the implementation. It is much more flexible than, for example, the NT one. If you wish, you can limit the amount of real memory used by MMF, at your choice on a "per file" or on a "per application" basis. One disadvantage of the implementation of MMF in OS/2 is more serious: the amount of address space for each application is limited by the 512Mb memory barrier (to be exact slightly less, around 400Mb). But this has been changed in Warp Server SMP, and probably will go away with release of Aurora and any future versions of the client. In any case, if you found the MMF library useful for your purposes, you can freely use it without any limitations. Usual disclaimer: use it at your own risk, there are no warranties at all and so on. CreditsMany thanks to Dmitry Niqiforoff (mailto:dniq@hippo.ru). This implementation of MMF is the result of a discussion with him. |