【发布时间】:2012-04-18 19:21:46
【问题描述】:
我正在尝试mmap,并附带以下示例代码:
int main() {
int fd;
char *filename = "/home/manu/file";
struct stat statbuf;
int i = 0;
char c = *(filename);
// Get file descriptor and file length
fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("fopen error");
}
if (fstat(fd, &statbuf) < 0) {
perror("fstat error");
}
printf("File size is %ld\n", statbuf.st_size);
// Map the file
char* mmapA = (char*) mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE,
fd, 0);
if (mmapA == MAP_FAILED) {
perror("mmap error");
return 1;
}
// Touch all the mapped pages
while (i < statbuf.st_size) {
c = mmapA[i];
i++;
}
c++;
// Close file descriptor
if (close(fd) == -1) {
perror("close");
return 1;
}
//Unmap file
munmap(mmapA, statbuf.st_size);
return EXIT_SUCCESS;
}
文件大小为 137948 字节 = 134.7 KB。 为了检查程序的内存,我使用顶部,主要是 RES 和 VIRT 列。我在三个不同的地方寻找这些值:
- 就在
mmap调用之前 - 就在
mmap通话之后 - 在读取所有映射内存以将文件有效加载到主内存后(页面错误后)
top 报告的值是
- VIRT = 1828 RES = 244
- VIRT = 1964 RES = 248
- VIRT = 1964 RES = 508
1964 - 1828 = 136,我猜以千字节为单位,因此完美匹配文件的大小。
但我无法理解 508 - 248 = 260 的 RES 差异 .. 为什么它与虚拟内存大小和文件大小不同?
【问题讨论】:
-
该操作系统被编码为最适合最常见的用途,或者最适合大声喊叫的客户的典型用途——它做了很多可能对您的使用没有意义的事情。你真的在乎吗?
-
@MartinBeckett 不,我根本不在乎;-) 这只是为了学习目的,我很好奇。
-
好吧,您总是可以阅读源代码;-) 我的猜测是,它总是在 mmap 上方保留一定的内存以防它扩展 - 即使在这里您以只读方式打开。但我不知道所以我没有添加这个作为答案
-
@MartinBeckett 这里看源码的问题,是我不知道在哪里看的吗?在我看来(但我完全不确定)它可能不在 mmap 实现中(因为它有效地映射了请求的虚拟内存量),但它是在读取时处理页面错误的代码。不是吗?
-
旁注。不要触摸每个字节,而是使用
sysconf(_SC_PAGE_SIZE);通常为 4096:i += pagesize;
标签: c linux linux-kernel mmap