c++ mmap读写示例

分3种情况测试文件读写情况下,page cache 等使用情况,也算是一个使用mmap的例子。文件大小为1GB。

  1. 直接读文件到内存中,内存中开辟文件大小的buffer进行读;
    • mem_total_uesed = 2GB
    • page_cache = 1GB
    • 程序堆栈占用= 1GB
  2. 使用mmap进行文件映射:
    • 仅仅映射,并不把其内容拷贝到内存缓冲区:mem_total_uesed = page_cache = 1GB,程序堆栈占用=0;
    • 将其内容拷贝到内存缓冲区;mem_total_uesed = 2GB;page_cache = 1GB;程序堆栈占用= 1GB
  3. mmap开辟一块1GB匿名内存进行写入:
    • mem_total_uesed = page_cache = 1GB;程序堆栈占用=0;
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
/**
* @Author yilan
* @create 2019/10/23 2:39 PM
* @brief 测试mmap内存使用情况
*/

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;

/*直接读文件到内存中,内存中开辟文件大小的buffer进行读*/
void read_file_to_buffer(const char* file_name) {
ifstream fl(file_name);
fl.seekg(0, ios::end );
size_t len = fl.tellg();
cout << len << endl;
char *ret = new char[len];
fl.seekg(0, ios::beg);
fl.read(ret, len);
fl.close();
// cout << ret << endl;
}


size_t get_file_size(const char* file_name) {
struct stat st;
stat(file_name, &st);
return st.st_size;
}

/*使用mmap进行文件映射*/
void read_file_from_mmap(const char* file_name) {
size_t file_size = get_file_size(file_name);
cout << file_size << endl;
//Open file
int fd = open(file_name, O_RDONLY, 0);
if (fd == -1){
cout << "Error open file for read" << endl;
return;
}
//Execute mmap
void* mmapped_data = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
if (mmapped_data == MAP_FAILED) {
close(fd);
cout << "Error mmapping the file" << endl;
return;
}

//Write the mmapped data buffer
/*将其内容拷贝到内存缓冲区*/
char *ret = new char[file_size];
memcpy(ret, mmapped_data, file_size);

//Cleanup
int rc = munmap(mmapped_data, file_size);
if (rc != 0) {
close(fd);
cout << "Error un-mmapping the file" << endl;
return;
}

// cout << ret << endl;

close(fd);
}

/*map开辟一块1GB匿名内存进行写入*/
void write_data_to_anoymous_mmap(){
cout << "come in the write_data_to_anoymous_mmap" << endl;
long file_size = 1 * 1024 * 1024 * 1024;
char* mmapped_data = (char*)mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (mmapped_data == MAP_FAILED) {
cout << "mmap failed: " << stderr << endl;
return;
}
cout << "start to write" << endl;
for (long i = 0; i < file_size; i++){
mmapped_data[i] = '\0';
}
cout << "end of write" << endl;
}

int main(int argc, char **argv) {
if (argc != 2) {
printf("wrong params! ./memory_consume_test [file_name]\n");
return -1;
}
char *file_name = argv[1];

read_file_to_buffer(file_name);
sleep(600);

read_file_from_mmap(file_name);
sleep(600);

write_data_to_anoymous_mmap();
sleep(600);

return 0;
}

#参考链接
A simple mmap() readonly example
mmap and read/write string to file
What is the purpose of MAP_ANONYMOUS flag in mmap system call?