![](/img/trans.png)
[英]Why does 'write()' take a const buffer while 'read()' doesn't?
[英]Mapped file doesn't take memory on read, but does on write
我观察到一种怪异的行为,其中一个大内存映射文件(2GB)在我从中读取时并没有占用实际的物理RAM,但是当我开始对其进行写入时却会占用。
int err = 0;
int fd = open("large_file", O_RDWR);
if (fd == -1) {
return errno;
}
void *map = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
err = errno;
goto out;
}
for (unsigned int i = 0; i < 2 << 30; i += PAGE_SIZE) {
volatile uint8_t val = 0xff;
// val = ((volatile uint8_t *) map)[i]; /* Doesn't take actual memory */
// ((volatile uint8_t *) map[i]) = val; /* Takes actual memory */
}
while (1)
sleep(10);
out:
if (fd != -1)
close(fd);
if (map != MAP_FAILED)
munmap(map, size);
return err;
我的笔记本电脑几乎是闲置的,除了测试过程外没有其他东西可以占用物理内存,因此您可以看到当我写入映射文件时实际上需要2GB(写时复制),而在读取时却不需要。 RES-SHR也适合我的两种情况。
我无法解释..内核映射新页面,无论它是对物理RAM的读取还是写入。 如果不存在,则应将其映射,并在出现页面错误异常后获取实际的RAM。 映射的文件未映射到其他进程,因此不共享。 测试过程是将文件映射到内存的唯一过程,也是第一个过程。
编辑:我添加了(volatile)关键字,以确保编译器不会优化关键代码。 这没有任何区别。 这段特定的汇编代码是从内存映射文件读取的输出:
mov BYTE PTR [rbp-0xbd],0xff /* volatile uint8_t val = 0xff; */
mov edx,DWORD PTR [rbp-0xbc]
mov rax,QWORD PTR [rbp-0xb0]
add rax,rdx
movzx eax,BYTE PTR [rax]
mov BYTE PTR [rbp-0xbd],al /* val = ((volatile uint8_t *)map)[i]; */
add DWORD PTR [rbp-0xbc],0x1000 /* i += PAGE_SIZE; */
有什么想法吗?
可能您的编译器只是优化了读取访问。 可以做到这一点,因为您永远不会做任何事情。 最简单的是更改val
的声明:
uint8_t volatile val = ... ;
但您也可以相应地声明map
:
uint8_t volatile*map = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
(声明map
类型也可以避免稍后再进行讨厌的转换。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.