Operating Systems 2 EN -- Laboratory 5 -- 2006-2007 -- info.uvt.ro
Appearance
Operating Systems 2 EN -- 2006-2007 -- info.uvt.ro
- Operating Systems 2 EN -- Assignment -- 2006-2007 -- info.uvt.ro
- Operating Systems 2 EN -- Laboratory 1 -- 2006-2007 -- info.uvt.ro
- Operating Systems 2 EN -- Laboratory 5 -- 2006-2007 -- info.uvt.ro
- Operating Systems 2 EN -- Laboratory 6 -- 2006-2007 -- info.uvt.ro
- Operating Systems 2 EN -- OSDI -- 2006-2007 -- info.uvt.ro
Memory mapped file
[edit]Links
[edit]Memory Mapped Files Memory mapped file -- Wikipedia article
Advantages
[edit]- Increased input / output performance
- Cached data
- Small data is read at once
- Minimizes the system calls
- Avoids memory copying
- Memory sharing
Disadvantages
[edit]- Increases the page faults ration
Suitable for
[edit]- Small but often input / output operations
- Random access
- Sharing data between processes
- Executable / library loading
Unsuitable for
[edit]- Sequential reading (streaming)
System call
[edit]#include <sys/mman.h>
void * mmap ( void * address, size_t size, int protection, int flags, int file_descriptor, off_t file_offset);
int munmap ( void * address, size_t size);
- address is a desired starting address for the mapped data. Usually it takes the value 0 and the operating system decides the actual address. It should be a multiple of the page size system parameter, obtained by getpagesize.
- size is the number of bytes to map from the file in memory. It should be a multiple of the page size system parameter.
- file_description is used to specify the backing file.
- file_offset the starting position inside the file. It should be a multiple of the page size system parameter.
- protection is a set of flags that mark the memory protection:
- PROT_NONE -- page can not be accessed;
- PROT_READ -- page can be read;
- PROT_WRITE -- page can be written;
- PROT_EXEC -- page can be executed.
- flags is a set of miscellaneous flags:
- MAP_FIXED -- makes the file system use only the desired address, or give an error;
- MAP_SHARED -- if a process modifies the mapped memory, all processes could see the modification;
- MAP_PRIVATE -- if a process modifies the mapped memory, the modification is only visible to the process;
- MAP_LOCKED -- the mapped pages are locked by using mlock;
- MAP_ANONYMOUS -- the mapped memory is not backed by a file, thus file descriptor and file offset are ignored;
- return value for mmap
- MAP_FAILED -- in case of error;
- a valid address -- in case of success.
- return value for munmap
- 0 -- in case of success;
- -1 -- in case of error;
Example
[edit]#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> void terminate (char * message) { printf ("[EE] %s\n", message); exit (1); } void terminate_if (int condition, char * message) { if (condition) terminate (message); } int main (int argc, char * * args) { char * file_name; int file_descriptor; void * file_address; size_t file_size; struct stat file_stat; int outcome; int page_size; int page_count; int page_index; char * page; terminate_if (argc != 2, "Invalid number of arguments"); file_name = args[1]; file_descriptor = open (file_name, O_RDONLY); terminate_if (file_descriptor == -1, "Can not open the file."); outcome = fstat (file_descriptor, &file_stat); terminate_if (outcome == -1, "Can not stat the file."); file_size = file_stat.st_size; file_address = mmap (0, file_size, PROT_READ, MAP_PRIVATE, file_descriptor, 0); terminate_if (file_address == MAP_FAILED, "Can not map the file."); page_size = 16; page_count = file_size / page_size; for (page_index = 0; page_index < page_count; page_index++) { page = ((char *) file_address) + (page_index * page_size); int i; printf ("%8x |", page_index * page_size); for (i = 0; i < page_size; i++) printf (" %02x", (unsigned char) page[i]); printf (" | |"); for (i = 0; i < page_size; i++) printf ("%c", ((page[i] >= 32) && (page[i] < 127) ? page[i] : ' ')); printf ("|\n"); } outcome = munmap (file_address, file_size); terminate_if (outcome != 0, "Can not unmap the file."); outcome = close (file_descriptor); terminate_if (outcome != 0, "Can not close the file."); }
Non blocking streams
[edit]When using non blocking operations, a read or write operation immediately returns when there is no data to be read / written.
For more information consult the man pages for:
- open
- read
Example
[edit]#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> void terminate (char * message) { printf ("[EE] %s\n", message); exit (1); } void terminate_if (int condition, char * message) { if (condition) terminate (message); } int main (int argc, char * * args) { char * file_name; int file_descriptor; struct stat file_stat; int loop; int outcome; char buffer[1024]; terminate_if (argc != 2, "Invalid number of arguments"); file_name = args[1]; file_descriptor = open (file_name, O_RDONLY | O_NONBLOCK); terminate_if (file_descriptor == -1, "Can not open the file."); loop = 1; while (loop) { printf ("[II] Reading...\n"); outcome = read (file_descriptor, buffer, sizeof (buffer)); if (outcome > 0) { int i; printf ("[>>] "); for (i = 0; i < outcome; i++) printf ("%c", buffer[i]); printf ("\n"); } else { if ((outcome == 0) || (errno == EAGAIN)) { printf ("[II] Sleeping...\n"); sleep (1); } else terminate ("Can not read from file."); } } outcome = close (file_descriptor); terminate_if (outcome != 0, "Can not close the file."); }