c - 从文件 I/OC/C++ 读取的内存映射
问题描述
我是内存映射领域的新手,我想知道是否有任何方法可以使用映射到字符串的内存来读取文本文件。我真的不知道如何开始编写代码。
解决方案
内存映射 I/O 的一般想法是,您告诉操作系统 (OS) 您想要什么文件,并且它(在进行了一些设置工作之后)告诉您该文件现在在内存中的什么位置。
一旦执行该合约,您应该能够以任何您希望的方式(例如使用memcpy
)将内容复制到该内存中或从该内存中复制,它会神奇地为您处理 I/O。
细节取决于您使用的操作系统,因为 ISO C 标准没有指定此行为 - 因此它是特定于操作系统的。
例如,Windows 使用此处显示的文件映射范例,而 Linux 使用mmap
允许您将已经打开的文件置于内存映射(通过其文件描述符)。
举个例子,这个 Linux 程序,主要是由于它的错误检查和进度报告,有点庞大,内存映射file.txt
文件并输出它的内容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
// Helper function to minimise error code in main.
static int clean(
int retVal, // value to return.
char *err, // error/NULL, allows optional %s for strerror(errno).
int fd, // fd/-1 to close.
void *filMem, // memory/NULL to unmap.
off_t sz, // size if unmapping.
void *locMem // memory/NULL to free.
) {
if (err) printf (err, strerror(errno));
if (locMem) free(locMem);
if (filMem) munmap(filMem, sz);
if (fd >= 0) close(fd);
return retVal;
}
int main(void) {
int fd = open("file.txt", O_RDONLY);
if (fd < 0) return clean(-1, "Can't open: %s\n", -1, NULL, 0, NULL);
printf("File opened okay, fd = %d.\n", fd);
off_t sz = lseek(fd, 0, SEEK_END);
if (sz == (off_t) -1) return clean(-1, "Can't seek: %s\n", fd, NULL, 0, NULL);
printf("File size is %ld.\n", sz);
void *fileArea = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
if (! fileArea) return clean(-1, "Can't map: %s\n", fd, NULL, 0, NULL);
printf("File mapped to address %p.\n", fileArea);
char *localArea = calloc(1, sz + 1);
if (! localArea) return clean(-1, "Can't allocate\n", fd, fileArea, sz, NULL);
memcpy(localArea, fileArea, sz);
printf("Data copied to %p, result is [\n%s]\n", localArea, localArea);
return clean(0, NULL, fd, fileArea, sz, localArea);
}
在我的本地系统上运行它,可以从以下脚本中看到结果:
pax$ cat file.txt
...This is the input file content.
pax$ ./testprog
File opened okay, fd = 3.
File size is 35.
File mapped to address 0x7f868a93b000.
Data copied to 0x1756420, result is [
...This is the input file content.
]
推荐阅读
- javascript - 人脸对比API
- javascript - 如何使分页位于选项卡内的页面底部?
- python - Discord.py - 使用计时器静音消息
- amazon-web-services - 如何根据某些属性将放大模型数据写入多个表并轻松查询?
- flutter - NullPointerException flutter_local_notifications 在版本更新后不起作用
- python - Google Nearby Places API 调用 - 请求无效
- jira - 在 Jira Software 中看不到“路线图”功能
- sql-server - 如果不在维度键属性上,则度量值组不受维度限制
- docker - 来自带有 Gunicorn 的 Docker 容器的 ModuleNotFoundError
- pdf - 如何使用 Illustrator SDK 将 XMP 添加到艺术作品中?