1# 文件映射
2## 概述
3
4文件映射功能。c_utils提供基于文件(file-backed)的内存映射。其将文件映射至进程的地址空间中,从而支持通过文件映射后的地址对文件进行读写操作。
5文件映射能够节省时间以及空间开销。此外,文件映射也可以支持跨进程的信息共享。
6
7## 涉及功能
8
9```mermaid
10classDiagram
11
12class MappedFile{
13    - String path_
14    - size_t offset_
15    - size_t size_
16    - MapMode mode_
17    - int mapProt_
18    - int mapFlag_
19    - int openFlag_
20    - const char* hint_
21    - char* data_
22    - bool isMapped_
23    - bool isNormed_
24    + MappedFile(std::string, size_t, off_t, MapMode, const char*)
25    + MappedFile(MappedFile&& other) noexcept
26    + MappedFile(const MappedFile& other)
27    + MappedFile& operator=(const MappedFile&)
28    + MappedFile& operator=(MappedFile&&) noexcept
29    + inline std::string& GetPath()
30    + inline const char* GetHint()
31    + inline MapMode GetMode()
32    + inline void ChangeSize(size_t size)
33    + inline void ChangeOffset(size_t offset)
34    + inline void ChangePath(string path)
35    + inline void ChangeMode(MapMode mode)
36    + inline void ChangeHint(const char* hint)
37    + ErrCode MapFile()
38    + ErrCode UnMapFile()
39    + ErrCode Resize()
40    + ErrCode Resize(size_t newSize, bool sync)
41    + ErrCode TurnNext()
42    + inline char* Begin()
43    + inline char* End()
44    + inline size_t Size()
45    + inline size_t StartOffset()
46    + inline size_t EndOffset()
47    + inline size_t PageSize()
48    + inline bool IsMapped()
49    + inline bool IsNormed()
50    - ErrCode NormSize()
51    - ErrCode NormMode()
52    - ErrCode SyncFileSize(size_t newSize)
53}
54
55class MapMode {
56    <<Enum>>
57    DEFAULT
58    SHARED
59    PRIVATE
60    READ_ONLY
61    READ_WRITE
62    CREAT_IF_ABSENT
63}
64
65```
66### OHOS::Utils::MapMode
67#### 描述
68```cpp
69enum class OHOS::Utils::MapMode;
70```
71映射模式枚举类,包含一系列枚举值以指定文件的映射模式。
72
73#### 枚举值
74|名称 | 值 | 描述 |
75| ---------- | ----- | ----------- |
76| DEFAULT | 0|  默认模式。等价于SHARED|READ_WRITE  |
77| PRIVATE | 2|  私有映射模式。对映射区域的写操作不会同步至文件中  |
78| SHARED | DEFAULT|  共享映射模式。对映射区域的写操作会同步至文件中  |
79| READ_ONLY | 4|  只读映射模式。该模式下若对映射区域进行写操作会导致进程退出  |
80| READ_WRITE | DEFAULT|  读写映射模式。该模式下支持对映射区域的读写操作  |
81| CREATE_IF_ABSENT | 8|  创建模式。当指定路径文件不存在时将创建文件后再进行映射  |
82
83### OHOS::Utils::MappedFile
84
85#### 描述
86```cpp
87class OHOS::Utils::MappedFile;
88```
89文件映射封装类,其用于管理一个文件的映射。
90
91`#include <mapped_file.h>`
92
93#### 公共静态常量
94|                | 名称           |
95| -------------- | -------------- |
96| constexpr off_t | **DEFAULT_LENGTH** <br>默认的映射区域大小。  |
97
98#### 公共成员函数
99| 返回类型       | 名称           |
100| -------------- | -------------- |
101| | **MappedFile**(const MappedFile & other) =delete<br>拷贝构造函数。禁止调用,不推荐单一进程内多个映射文件对象对同一段地址进行操作, 可能导致内存泄漏、内存非法访问等问题。  |
102| | **MappedFile**(MappedFile && other) |
103| | **MappedFile**(std::string & path, MappedMode mode =MapMode::DEFAULT, off_t offset =0, off_t size =DEFAULT_LENGTH, const char * hint =nullptr)<br>构造函数。至少需要显式指定待映射的文件路径。  |
104| virtual | **~MappedFile**() |
105| char * | **Begin**() const<br>获取映射后的映射区域首地址。  |
106| bool | **ChangeHint**(const char * hint)<br>指定被映射文件区域的大小  |
107| bool | **ChangeMode**(MappedMode mode)<br>指定被映射文件区域的大小  |
108| bool | **ChangeOffset**(off_t offset)<br>指定被映射文件区域的偏移量。  |
109| bool | **ChangePath**(const std::string & path)<br>指定被映射文件对应路径。  |
110| bool | **ChangeSize**(off_t size)<br>指定被映射文件区域的大小。  |
111| ErrCode | **Clear**(bool force =false)<br>清除映射。解除映射区域,重置所有映射状态及参数,关闭已打开文件。  |
112| char * | **End**() const<br>获取映射后的映射区域尾地址。  |
113| off_t | **EndOffset**() const<br>获取当前指定映射区域尾地址对应的文件偏移量。  |
114| int | **GetFd**() const<br>获取当前指定文件对应的文件描述符  |
115| const char * | **GetHint**() const<br>获取当前指定的映射区域期望首地址  |
116| MappedMode | **GetMode**() const<br>获取当前指定的文件映射模式  |
117| const std::string & | **GetPath**() const<br>获取当前指定的文件路径  |
118| bool | **IsMapped**() const<br>指示是否为已映射状态。  |
119| bool | **IsNormed**() const<br>指示当前参数是否已标准化。  |
120| ErrCode | **Map**()<br>使用当前参数映射文件至内存。参数将被标准化。  |
121| ErrCode | **Normalize**()<br>标准化指定映射参数。  |
122| MappedFile & | **operator=**(const MappedFile & other) =delete<br>拷贝赋值重载函数。禁止调用,不推荐单一进程内多个映射文件对象对同一段地址进行操作, 可能导致内存泄漏、内存非法访问等问题。  |
123| MappedFile & | **operator=**(MappedFile && other) |
124| char * | **RegionEnd**() const<br>获取映射后的映射区域所在页的尾地址。  |
125| char * | **RegionStart**() const<br>获取映射后的映射区域所在页的首地址。  |
126| ErrCode | **Resize**()<br>按照当前参数重新进行映射。  |
127| ErrCode | **Resize**(off_t newSize, bool sync =false)<br>调整映射区域大小,同时保持起始地址不变。可选择同步调整文件大小。  |
128| off_t | **Size**() const<br>获取当前指定的映射区域大小。  |
129| off_t | **StartOffset**() const<br>获取当前指定映射区域首地址对应的文件偏移量。  |
130| ErrCode | **TurnNext**()<br>“翻页”。将当前参数对应的文件中的被映射区域向后平移。注意“翻页”中的“页”并不代表 内存页。  |
131| ErrCode | **Unmap**()<br>解映射当前已映射文件。建议在参数已标准化时调用该方法,避免内存问题。  |
132| off_t | **PageSize**()<br>获取当前内存页大小。  |
133
134## 使用示例
135
1361. 使用方法(伪代码)
137
138```c++
139    // 1. 创建文件
140    std::string filename = "test_read_write_1.txt";
141    std::string content = "Test for normal use.";
142    filename.insert(0, SUITE_PATH).insert(0, BASE_PATH);
143    RemoveTestFile(filename);
144
145    CreateTestFile(filename, content); // 该方法创建filename指定的文件并写入content
146
147    // 2. 构造MappedFile对象并进行映射
148    MappedFile mf(filename);
149    mf.Map();
150
151    // 3. 映射后可通过Begin()方法获取起始地址,并从中读取数据
152    std::string readout;
153    for (char* cur = mf.Begin(); cur <= mf.End(); cur++) {
154        readout.push_back(*cur);
155    }
156
157    // 4. 同样也可以向对应地址中写入数据
158    std::string toWrite("Complete.");
159    char* newCur = mf.Begin();
160    for (std::string::size_type i = 0; i < toWrite.length(); i++) {
161        (*newCur) = toWrite[i];
162        newCur++;
163    }
164    std::string res;
165    LoadStringFromFile(filename, res); // res的内容应与toWrite覆盖后的原本内容一致
166
167    // 5. 注意,当试图向End()指示的地址以外(但是不超过该地址一个内存页)写入时,写入不会越界但是写入内容一定不会回写至原文件中。
168    char* trueEnd = mf.RegionEnd(); // RegionEnd() 返回End()指示地址所在的内存页末尾。
169    ASSERT_GT(trueEnd, mf.Begin());
170
171    (*trueEnd) = 'E'; // 可以向trueEnd指向地址写入数据
172
173    EXPECT_EQ((*trueEnd), 'E'); // 同样也可以读出
174
175    std::string res1;
176    LoadStringFromFile(filename, res1);// 但是文件中不会同步结果, res1仍将和res内容相同。
177
178    // 6. MappedFile对象会在析构时自动解除映射,并关闭内部创建的fd。当然也可以手动解除映射。
179    mf.Unmap();
180
181    RemoveTestFile(filename); // 该方法删除了创建的文件
182```
183
1842. 测试用例编译运行方法
185
186- 测试用例代码参见 base/test/unittest/common/utils_mapped_file_test.cpp
187
188- 使用开发者自测试框架,使用方法参见:[开发自测试执行框架-测试用例执行](https://gitee.com/openharmony/testfwk_developer_test#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E6%89%A7%E8%A1%8C)
189
190- 使用以下具体命令以运行`mapped_file.h`对应测试用例
191
192```bash
193run -t UT -tp utils -ts UtilsMappedFileTest
194```
195