Io 从概念上理解内存映射

Io 从概念上理解内存映射,io,virtual-memory,memory-mapped-files,mmu,Io,Virtual Memory,Memory Mapped Files,Mmu,我已经在上问过这个问题,但决定也把它贴在这里 我读过一些关于堆栈交换的博客和问题,但我无法理解内存映射文件的真正缺点是什么。我经常看到下列情况: 无法使用32位地址空间对大文件(>4GB)进行内存映射。现在我觉得这很有道理 我想到的一个缺点是,如果内存映射的文件太多,可能会导致可用系统资源(内存)=>减少,可能会导致页面被逐出=>可能会出现更多页面错误。因此,在决定要映射哪些文件以及它们的访问模式时需要谨慎 内核映射和数据结构的开销-。我甚至不会质疑这个前提,因为我对Linux内核的内部结构了解

我已经在上问过这个问题,但决定也把它贴在这里

我读过一些关于堆栈交换的博客和问题,但我无法理解内存映射文件的真正缺点是什么。我经常看到下列情况:

  • 无法使用32位地址空间对大文件(>4GB)进行内存映射。现在我觉得这很有道理

  • 我想到的一个缺点是,如果内存映射的文件太多,可能会导致可用系统资源(内存)=>减少,可能会导致页面被逐出=>可能会出现更多页面错误。因此,在决定要映射哪些文件以及它们的访问模式时需要谨慎

  • 内核映射和数据结构的开销-。我甚至不会质疑这个前提,因为我对Linux内核的内部结构了解不多。:)

  • 如果应用程序试图读取未加载到页面缓存中的文件部分,它(应用程序)将招致页面错误形式的惩罚,这反过来意味着操作的I/O延迟增加

  • 问题#1:标准文件I/O操作不也是这样吗?如果应用程序试图读取尚未缓存的文件的一部分,它将导致系统调用,从而导致内核从设备加载相关页/块。最重要的是,页面需要复制回用户空间缓冲区

    这里的问题是页面错误总的来说比系统调用更昂贵吗?我的解释是什么?是因为页面错误阻塞=>线程没有在CPU之外调度=>我们在浪费宝贵的时间吗?还是我在这里遗漏了什么

  • 不支持内存映射文件的异步I/O
  • 问题#2:支持内存映射文件的异步I/O是否存在体系结构限制,或者仅仅是因为没有人愿意这样做

    问题#3:有点含糊,但我的解释是,内核可以对标准I/O进行预读(即使没有fadvise()),但不会对内存映射文件进行预读(除非使用madvice()发出通知)。这准确吗?如果这句话事实上是真的,那么这就是为什么系统调用标准I/O可能比调用内存映射文件更快的原因吗?内存映射文件几乎总是会导致页面错误

    问题#1:标准文件I/O操作不也是这样吗?如果应用程序试图读取尚未缓存的文件的一部分,它将导致系统调用,从而导致内核从设备加载相关页/块。最重要的是,页面需要复制回用户空间缓冲区

    您对缓冲区执行
    读取
    ,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;对于您的流程和系统中的其他人。如果你是真的