Linux 内存模型— 物理内存 / 虚拟地址 / 用户内核空间 / mmap

📅 2026/7/9 1:27:19
Linux 内存模型— 物理内存 / 虚拟地址 / 用户内核空间 / mmap
围绕几个核心疑问内核空间、用户空间申请的内存和物理内存什么关系用户空间虚拟地址和内核空间虚拟地址是不同的吗物理内存是不是分成两部分一部分给用户、一部分给内核驱动/内核/应用三者操作内存的区别mmap 零拷贝的原理一、最底层事实物理内存是唯一真实的物理内存(RAM) 内存条 / 芯片里的 DDR真实、唯一的硬件。每个字节有个物理地址。一切数据最终都存在物理内存里其他都是说法。二、虚拟地址一层障眼法问题应用若直接用物理地址会乱冲突、不安全、会踩坏内核。解决每个应用看到的都是虚拟地址不是真实物理地址。 硬件 MMU 自动把虚拟地址翻译成物理地址。应用以为访问 0x1000(虚拟地址) ↓ MMU 硬件翻译(查页表) 实际访问物理地址 0x8A3000(真实位置)效果每个应用都以为自己独占从 0 开始的内存但各自虚拟地址被翻译到不同物理位置互不干扰。页表虚拟→物理的翻译表操作系统给每个进程维护一张页表记录虚拟地址 → 物理地址。进程A页表: 虚拟 0x1000 → 物理 0x8A3000 进程B页表: 虚拟 0x1000 → 物理 0x5F2000 ← 同样虚拟地址,翻译到不同物理!MMU 访问内存时自动查页表翻译应用无感。三、用户空间 vs 内核空间针对虚拟地址划分每个进程的虚拟地址空间分两部分以32位、3G/1G 为例┌─────────────────────┐ 高地址 │ 内核空间 │ 高地址区所有进程共享同一个内核 ├─────────────────────┤ 分界线 │ 用户空间 │ 低地址区每个进程独立 └─────────────────────┘ 低地址用户空间内核空间谁用应用内核、驱动每个进程独立(各自映射不同物理内存,互相隔离)共享(所有进程看到同一个内核)权限低(只能访问用户空间)高(能访问全部)虚拟地址位置低地址高地址✅ 用户空间虚拟地址 和 内核空间虚拟地址是不同的(一个在低区,一个在高区)。四、⚠️ 关键纠正物理内存不分用户/内核常见误解物理内存分成两半一半给用户、一半给内核。❌正确物理内存是一个统一的池子不预先划分按需动态分配。物理内存 统一池子 同一块物理内存: 这会儿映射给用户空间用 回收后又可映射给内核空间用 → 动态分配,没有固定划分区分两件事混淆的根源虚拟地址空间物理内存分不分用户/内核分!(高内核、低用户,固定)不固定划分(统一池子,按需分配)性质逻辑上的地址划分真实存储资源用户空间/内核空间是针对虚拟地址空间的划分不是针对物理内存的。虚拟地址分家物理内存共享一个池子靠映射关系决定一块物理内存这会儿归谁。例子应用A malloc → 分到物理块 0x8A3000(此刻映射给用户空间) 应用A 释放 → 0x8A3000 回收到池子 内核 kmalloc → 分到物理块 0x8A3000(同一块!此刻映射给内核空间)同一块物理内存先给用户用、回收后又给内核用。物理内存不认用户/内核 由当前映射到哪个虚拟地址决定归谁。比方停车场门禁卡分员工卡(内核虚拟地址)/访客卡(用户虚拟地址) →卡分类(虚拟地址分内核/用户)但停车位不分谁来分个空位、走了回收再给别人 →车位共用池(物理内存统一分配)五、申请内存到底申请了什么应用 mallocchar *p malloc(1024);OS 在用户空间划一段虚拟地址页表登记这段虚拟地址 → 某段物理内存返回虚拟地址(p是虚拟地址)往p写 → MMU 翻译 → 实际写进物理内存内核/驱动 kmalloc / vmallocchar *p kmalloc(1024, GFP_KERNEL);类似但在内核空间划虚拟地址映射到物理内存。kmalloc vs vmallockmalloc: 虚拟[连续] → 物理[连续] 小块、需物理连续(如DMA) vmalloc: 虚拟[连续] → 物理[分散] 大块,物理不连续,页表拼成虚拟连续vb2 的vb2_vmalloc_memops用 vmalloc 分配图像缓冲区(大块,物理不连续没关系)。六、三者操作内存的区别能访问的内存用什么分配地址类型应用只有自己的用户空间malloc用户空间虚拟地址驱动内核空间 (借助函数)用户空间kmalloc/vmalloc内核空间虚拟地址内核全部各种各种应用被关在用户空间(出不去)内核/驱动在内核空间权限高中间隔着墙不能直接互访跨墙传数据的两种方式拷贝copy_from_user/copy_to_user— 复制一份过墙。安全但有开销(ioctl 参数用它)。映射(mmap)让墙两边虚拟地址指向同一物理内存 — 零拷贝(vb2 图像用它)。七、mmap 零拷贝原理内存知识的落地① vb2 用 vmalloc 分配缓冲区 → 内核空间虚拟地址 → 映射到某片物理内存 → 摄像头硬件把图像写进这片物理内存 ② 应用要读,但缓冲区在内核空间,应用(用户空间)访问不了 ③ mmap: 在应用用户空间也划一段虚拟地址,映射到【同一片物理内存】 ④ 结果: 内核虚拟地址 和 用户虚拟地址 指向同一块物理内存 → 数据只有一份,两边都能访问,不用拷贝(零拷贝)内核虚拟地址 ─┐ ├─→ 同一片物理内存(图像数据) 用户虚拟地址 ─┘mmap 的本质让用户空间虚拟地址和内核空间虚拟地址通过页表映射到同一片物理内存。 不是拷贝数据而是共享同一块物理内存 → 零拷贝。八、一句话总结物理内存是唯一真实的、统一的池子不预先分用户/内核。虚拟地址是障眼法 由页表翻译成物理地址。虚拟地址空间分用户区(低)/内核区(高)——两者虚拟地址不同物理内存不分靠映射关系决定一块物理内存这会儿归谁。malloc/kmalloc申请的是 虚拟地址背后映射到物理内存。应用只能碰用户空间内核/驱动能碰内核空间跨墙靠拷贝或mmap 映射。mmap 零拷贝 让用户与内核两个虚拟地址映射到同一片物理内存。九、术语速查术语含义物理内存真实的内存条/DDR唯一真实存在统一池子虚拟地址进程看到的地址,由页表翻译成物理地址页表虚拟地址→物理地址的翻译表,每进程一份MMUCPU 里做地址翻译的硬件用户空间虚拟地址低区,应用用,各进程独立内核空间虚拟地址高区,内核/驱动用,全系统共享malloc应用申请用户空间虚拟地址kmalloc内核申请,虚拟物理都连续vmalloc内核申请,虚拟连续物理分散,适合大块copy_from/to_user跨墙拷贝数据mmap让用户与内核虚拟地址映射到同一物理内存,零拷贝