-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmmap_manager.cpp
112 lines (100 loc) · 2.99 KB
/
mmap_manager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <sys/mman.h>//mmap, munmap
#include <sys/stat.h>//open
#include <fcntl.h>//O_RDWR, O_RDONLY
#include <unistd.h> //close
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "mmap_manager.h"
namespace{
//! Get the size of file
//
//! @param fn filename to check the size
//! @return file size in Byte
size_t get_filesize(const char *fn){
std::ifstream ifs(fn);
if(!ifs){
std::cerr << "Failed to open " << fn << std::endl;
std::abort();
}
return ifs.seekg(0, std::ios::end).tellg();
}
} //end of unnamed namespace
struct mmap_manager::impl{
//! File descriptor of mapped file
int fd;
//! The head of mapped area
void *mapped_area;
//! Mapped size
size_t mapped_size;
impl(const char *, bool, size_t);
~impl();
};
//! Constructor
//
//! @param filename filename to be mapped
//! @param is_writable accessibility of the mapped region
//! @param size size of mapped region in Byte
mmap_manager::impl::impl(const char *filename, bool is_writable, size_t size){
fd = open(filename, O_SYNC | (is_writable ? O_RDWR : O_RDONLY));
if(fd < 0){
perror(filename);
std::abort();
}
mapped_size = size;
mapped_area = mmap(NULL, size, PROT_READ | (is_writable ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
if(mapped_area == MAP_FAILED){
perror(filename);
std::abort();
}
}
//! Destructor
mmap_manager::impl::~impl(){
if(msync(mapped_area, mapped_size, MS_SYNC)){
perror("msync");
std::abort();
}
if(munmap(mapped_area, mapped_size)){
perror("munmap");
std::abort();
}
if(close(fd)){
perror("close");
std::abort();
}
}
//! Constructor (Map the whole file)
//
//! @param filename name of existing file to map
//! @param is_writable whether the file can be modified
//! @arg true the file is mapped as a readable/writable
//! @arg false the file cannnot be modified. If the area is modified, you will receive SIGSEGV.
mmap_manager::mmap_manager(const char *filename, bool is_writable){
pimpl = new impl(filename, is_writable, get_filesize(filename));
}
//! Constructor (Map specied length from the head of the file)
//
//! @param filename name of existing file to map
//! @param is_writable whether the file can be modified
//! @arg true the file is mapped as a readable/writable
//! @arg false the file cannnot be modified. If the area is modified, you will receive SIGSEGV.
//! @param map_size the size of mapped region in Byte
mmap_manager::mmap_manager(const char *filename, bool is_writable, size_t map_size){
pimpl = new impl(filename, is_writable, std::min(get_filesize(filename), map_size));
}
//! Destructor
mmap_manager::~mmap_manager(){
delete pimpl;
}
//! Get the head address of mapped memory
//
//! @return the head of memory area
void * mmap_manager::get_ptr()const{
return pimpl->mapped_area;
}
//! Get memory mapped size
//
//! @return mapped area in Byte
size_t mmap_manager::get_size()const{
return pimpl->mapped_size;
}