mmap
内存映射(Memory Mapping)是一种通过将文件或设备内容直接映射到进程的虚拟内存空间中,以实现高效数据访问的技术。它允许进程将文件或设备的一部分作为内存的一部分进行访问,而不需要通过文件 I/O 系统调用来读取或写入数据。内存映射的方式主要有两种:
文件映射:将文件的一部分映射到进程的虚拟内存空间中。进程可以像操作普通内存一样读取和修改文件内容。例如,使用 mmap 系统调用将文件内容映射到内存。当文件映射为共享模式(MAP_SHARED)时,不同进程对该映射区域的更改会相互可见,适合实现进程间通信和数据共享。
匿名映射:在进程内分配一块未关联任何文件的内存区域,通常用于进程自身的内存管理,如栈、堆等。这种方式没有磁盘文件作为后备存储,数据仅存在于内存中,适合需要动态分配和释放的内存区域。
工作机制
页表项映射:系统为每个内存映射区域创建页表项。通过页表,CPU 可以将虚拟地址翻译为物理地址。
按需调页:映射区域在最初并不将所有页面加载到内存中,而是采用“按需调页”的机制。当进程第一次访问该区域时,会触发缺页中断,将对应的页面加载到内存中,这种懒加载机制提升了内存效率。
共享与私有
MAP_SHARED:多个进程可以共享同一映射区域。更改会直接写入文件,所有共享该区域的进程可以立即看到修改。
MAP_PRIVATE:提供写时复制(Copy-on-Write)机制,允许进程独立修改数据,不影响其他进程的视图,适合需要数据隔离的应用。
MAP_SHARED
当我们在两个进程之间创建了一个共享内存区域(通过 mmap 的 MAP_SHARED 标志),该内存区域会映射到两个进程的虚拟地址空间中。最初,这个区域并不会立即加载到实际的物理内存,而只是作为一种映射关系存在。这样,当其中一个进程第一次尝试读取或写入该区域时,就会触发缺页中断(page fault),系统才会实际将该内存区域加载到物理内存中并开始使用。
当进程共享同一个页面时,它们在任何时候看到的内容都是相同的。这种机制适用于一些不可变的内容,例如程序的只读代码段(也称为“文本”段),它可以在多个进程间共享。这样,每当一个进程需要访问该代码段时,通过缺页中断将该段加载到内存,而不需要在每个进程中重复加载。
MAP_PRIVATE
这里变成 private object了 !!!
MMAP 写时复制(Copy on Write, COW)的工作原理。
在写时复制机制中,初始时内存是共享的,多个进程可以访问相同的数据。然而,如果某个进程试图更改数据,就会触发写时复制。操作系统会在该进程尝试修改数据时,为该进程创建该数据的独立副本,确保其他进程不会受到此次更改的影响。这样做不仅提高了内存利用效率,而且保持了进程之间的数据独立性。
例如,两个进程共享一块只读的数据页,当其中一个进程尝试写入50进入该页时,操作系统会将该页复制一份并赋予写入权限,然后仅允许该进程访问副本,而其他进程继续访问原始页。这种方式确保了仅在需要时才分配新的内存页,从而节省了内存。