Io 从概念上理解内存映射
我已经在上问过这个问题,但决定也把它贴在这里 我读过一些关于堆栈交换的博客和问题,但我无法理解内存映射文件的真正缺点是什么。我经常看到下列情况:Io 从概念上理解内存映射,io,virtual-memory,memory-mapped-files,mmu,Io,Virtual Memory,Memory Mapped Files,Mmu,我已经在上问过这个问题,但决定也把它贴在这里 我读过一些关于堆栈交换的博客和问题,但我无法理解内存映射文件的真正缺点是什么。我经常看到下列情况: 无法使用32位地址空间对大文件(>4GB)进行内存映射。现在我觉得这很有道理 我想到的一个缺点是,如果内存映射的文件太多,可能会导致可用系统资源(内存)=>减少,可能会导致页面被逐出=>可能会出现更多页面错误。因此,在决定要映射哪些文件以及它们的访问模式时需要谨慎 内核映射和数据结构的开销-。我甚至不会质疑这个前提,因为我对Linux内核的内部结构了解
读取
,I/O设备会将其复制到那里。还有异步读取或AIO,当设备提供数据时,内核将在后台传输数据。您可以对线程和读取执行相同的操作。对于mmap
情况,您没有控制权或不知道页面是否已映射。read
的情况更为明确。这是从,
ssize_t read(int fd, void *buf, size_t count);
您可以指定buf
和count
。您可以显式地将数据放置在程序中所需的位置。作为一名程序员,您可能知道数据不会被再次使用。随后对read
的调用可以重用上次调用中相同的buf
。这有多重好处;最容易看到的是更少的内存使用(或者至少是地址空间和MMU表)mmap
不知道将来是否仍将访问某个页面mmap
不知道页面中只有一些数据是感兴趣的。因此,read
更为明确
假设磁盘上有4096条大小为4095字节的记录。您需要读取/查看两个随机记录并对其执行操作。对于read
,您可以使用malloc()
或使用静态字符缓冲区[2][4095]
数据分配两个4095缓冲区。mmap()。访问每个mmap
记录时,记录跨越两页。这会导致每个记录访问出现两个页面错误。此外,内核必须分配四个TLB/MMU页面来保存数据
或者,如果read
到顺序缓冲区,则只需要两个页面,只有两个系统调用(read
)。此外,如果对记录的计算非常广泛,则缓冲区的位置将使其比mmap
数据快得多(CPU缓存命中)
最重要的是,页面需要复制回用户空间缓冲区
这本书可能没有你想象的那么糟糕。CPU将缓存数据,以便下一次访问不必从主存重新加载,其速度可以比一级CPU缓存慢100倍
在上述情况下,mmap
可能会占用读取时间的两倍以上
这里是不是担心页面错误总的来说比系统调用更昂贵——我对Linus Torvalds在这里所说的解释?是因为页面错误阻塞=>线程没有在CPU之外调度=>我们在浪费宝贵的时间吗?还是我在这里遗漏了什么
我认为主要的一点是,您无法控制mmap
。您mmap
文件,不知道是否有任何部分在内存中。如果您只是随机访问该文件,那么它将继续从磁盘读回该文件,并且您可能会在不知道的情况下根据访问模式受到重击。如果访问纯粹是按顺序进行的,那么乍一看可能不会更好。然而,通过将新块重新读取到相同的用户缓冲区,将更好地利用CPU的一级/二级CPU缓存和TLB;对于您的流程和系统中的其他人。如果你是真的