// MMap.h -- mmap() system call wrapper class // 11/4/97 // 11/29/97 modified for private mappings of /dev/zero #ifndef __MMAP_H #define __MMAP_H #pragma interface "MMap.h" #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> /* MMap -- wrapper class for the system call mmap() This wrapper class provides a simple interface to the system call mmap(). The object contains: int fd -- the file descriptor of the file to be mapped const char *fileName -- the name of the file to be mapped size_t length -- the length of the mapped region in bytes off_t offset -- the offset of the mapped region in the file int prot -- the protection mode of the mapping int flags -- the flags of the mapping void *paddr -- the address of the mapped region in the main memory */ class MMap { protected: int fd; // file descriptor char *fileName; // file name size_t length; // length of the mapped region in bytes off_t offset; // offset of the mapped region in the file int prot; // protection mode of mmap int flags; // mmap flags void *paddr; // mapped addr in main memory public: // constructors /* MMap(fd) -- constructor by a file descriptor parameters: int FD -- the file descriptor int p -- the protection mode */ MMap(int FD = -1, int p = PROT_READ | PROT_WRITE): fd(FD), fileName(0), prot(p), flags(MAP_SHARED), paddr(0) {} /* MMap(MMap &) -- constructor by another MMap object parameter: MMap &m -- the MMap object, whose mapping is not inherited */ MMap(MMap &m): fd(m.fd), fileName(0), prot(m.prot), flags(m.flags), paddr(0) {} /* MMap(file) -- general constructor by a file name parameters: const char *file -- the file name for mapping int p -- the protection mode */ MMap(const char *file, int p = PROT_READ | PROT_WRITE) : paddr(0) { struct stat st; static const char DevZero[] = "/dev/zero"; if (file == 0) { fd = -1; return; } if (strcmp(file, DevZero) != 0) { if (stat(file, &st) != 0) { fd = -1; return; } if (!S_ISREG(st.st_mode)) { fd = -1; return; } if (st.st_size <= 0) { fd = -1; return; } } if (p & PROT_WRITE) { if ((fd = open(file, O_RDWR)) == -1) { fd = -1; return; } } else { if ((fd = open(file, O_RDONLY)) == -1) { fd = -1; return; } } fileName = new char[strlen(file) + 1]; strcpy(fileName, file); prot = p; if (strcmp(file, DevZero) != 0) { flags = MAP_SHARED; } else { flags = MAP_PRIVATE; } } /* assignment operater with another MMap object parameter: MMap &m -- another MMap object, whose mapping is not inherited */ MMap &operator=(MMap &m) { fd = m.fd; fileName = 0; prot = m.prot; flags = m.flags; paddr = 0; return *this; } /* ~MMap() -- destructor This destructor unmaps the existing mapping. */ ~MMap() { if (fd != -1 && paddr != 0) { this->unmap(); if (fileName) { close(fd); } } } /* map -- map a region to the main memory parameters: off_t off -- the offset of the beginning of the region in the file size_t len -- the length of the region in bytes return value: void * -- the address of the mapped region in the main memory, 0 when mapping failed */ void *map(off_t off, size_t len) { if (fd == -1) return 0; if (paddr != 0) // already mapped munmap(paddr, length); // unmap the previous mapping paddr = mmap(0, len, prot, flags, fd, off); if ((int)paddr == -1) { paddr = 0; return 0; } offset = off; length = len; return paddr; } /* unmap -- unmap the region parameter: none return value: int -- -1 when unmapping failed */ int unmap() { if (fd == -1) return -1; if (paddr == 0) return -1; if (munmap(paddr, length) != 0) { return -1; } else { paddr = 0; return 0; } } /* sync -- synchronize the memory with the file parameter: int syncflags -- MS_SYNC for synchronous operation, MS_ASYNC for asynchronous operation return value: int -- -1 when synchronization failed */ int sync(int syncflags = MS_SYNC) { if (fd == -1) return -1; if (paddr == 0) return -1; if (msync(paddr, length, syncflags) != 0) return -1; else return 0; } // accessors // get the file descriptor int getFd() { return fd; } // get the file name const char *getFileName() { return fileName; } // get the address of the mapped region in the main memory inline void *getAddr() { return paddr; } // get the length of the mapped region inline size_t getLength() { return paddr ? length : -1; } // get the offset of the mapped region in the file inline off_t getOffset() { return paddr ? offset : -1; } }; #endif // __MMAP_H