一个简单的 mmap() 只读示例
问题:
你想使用 sys/stat.h POSIX 头文件中的 mmap() 映射文件以供读取(不是写入)。你在互联网上找不到任何简单的裸示例。
解决方案
如果你只对高级包装器感兴趣,请查看此 boost::iostreams mmap 示例和 boost::iostreams mmap 参考。但请记住,boost::iostreams 不提供 mmap() 的所有功能,而且 boost::iostreams 是相当大的依赖(你需要链接库!)。然而,对于更好地移植到非 unix 系统,它可能是最佳选择。
这是一个基于 mmap() 的最小 cat 实现。它效率不高,但演示了重要概念。它使用此之前的文章中基于 stat() 的 getFilesize() 函数
mmap_cat_example.cpp
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
size_t getFilesize(const char* filename) {
struct stat st;
stat(filename, &st);
return st.st_size;
}
int main(int argc, char** argv) {
size_t filesize = getFilesize(argv[1]);
//打开文件
int fd = open(argv[1], O_RDONLY, 0);
assert(fd != -1);
//执行 mmap
void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
assert(mmappedData != MAP_FAILED);
//将 mmap 数据写入 stdout(= FD #1)
write(1, mmappedData, filesize);
//清理
int rc = munmap(mmappedData, filesize);
assert(rc == 0);
close(fd);
}使用以下命令编译
build_mmap_example.sh
g++ -o mmap-example mmap-example.cpp像这样运行:
run_mmap_example.sh
echo "hello mmap world" > test.txt
./mmap-example test.txt逐步讨论
步骤 1: 获取文件大小。你需要在调用 mmap 之前知道,但也可以只 mmap 子集。
步骤 2: 打开文件。记住你不能直接使用 fopen() 函数(你可以在 FILE 对象上使用 fileno()),因为你需要文件描述符!在这种情况下我们使用 O_RDONLY,因为我们想只读 mmap()。
步骤 3: 使用这些参数调用 mmap():
- NULL:让内核决定在哪个地址 mmap。这是推荐的地址参数。
- filesize:文件大小。对于只读 mmap,只有 <= 实际文件大小的值才有意义。
PROT_READ:以只读方式映射文件(换句话说,使用只读页面保护)MAP_PRIVATE:通常这意味着不要将对 mmap 内存的更改写回文件,但我们反正以只读方式映射了,所以使用这个或 MAP_SHARED 没有明显区别。MAP_POPULATE:让内核预加载文件部分。这是性能优化。没有绝对必要使用它。- fd:要映射的 unix 文件描述符(如果你有
FILE*,可以使用fileno()获取描述符编号)。必须以 * 0:从文件开头的偏移量打开。0 因为我们想映射整个文件
有关详细的 mmap() 参考,请参见 Opengroup mmap 页面
错误检查
上述实现没有正确检查错误,因为它只是一个最小示例。
在任何情况下,你至少应该检查 mmap() 返回的值是否*== MAP_FAILED*。详情请参见 Opengroup mmap 页面。
更新 2013/09/26: 在清理部分关闭文件描述符
更新 2016/01/07: 断言 != MAP_FAILED 而不是 NULL(感谢 Erik Sjölund)
Check out similar posts by category:
C/C++
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow