1. Linux内存管理全景:物理内存与虚拟内存、MMU与页表、用户空间与内核空间划分

大家好,我是你们的老朋友。今天咱们来聊聊Linux内存管理这个“大块头”。说实话,我刚开始接触内核时,这块内容是最让我头疼的。但后来我发现,只要把几个核心概念理清楚,整个内存管理就像一张地图一样清晰。

嗯,咱们先从最基础的说起。

1.1 物理内存 vs 虚拟内存:一个“骗术”的艺术

物理内存,就是板子上焊的那几颗DDR颗粒。你插了4GB,它就是4GB。但问题是,你的程序可能觉得自己能用的内存远不止4GB。这是怎么回事?

说白了,这就是虚拟内存的功劳。每个进程都活在一个“假想世界”里——它以为自己独占着整个地址空间(32位下是4GB,64位下更是大到离谱)。但实际上,它看到的地址都是假的,是虚拟地址。

核心观点:虚拟内存是一种“骗术”,它让每个进程都觉得“我拥有整个内存”。而物理内存,才是那个真正干活儿的“老实人”。

我在项目中遇到过这样一个场景:一个嵌入式设备只有256MB内存,但我们要同时跑三个大型应用。每个应用都觉得自己有1GB空间可用。为什么能跑起来?因为虚拟内存让它们“共享”了那256MB物理内存,而且通过换页机制,把不常用的数据暂时挪到Flash上。

1.2 MMU与页表:虚拟到物理的“翻译官”

虚拟地址怎么变成物理地址?这就要靠MMU(内存管理单元)了。MMU是CPU内部的一个硬件模块,它负责把虚拟地址“翻译”成物理地址。

翻译的依据是什么?是页表。

页表,你可以把它理解成一张“映射表”。它记录了每个虚拟页面(通常是4KB大小)对应哪个物理页面。举个例子:

虚拟地址 0x1000 → 页表查询 → 物理地址 0x8000
虚拟地址 0x2000 → 页表查询 → 物理地址 0x9000

为什么会这样设计?你想想看,如果没有MMU,所有程序都直接操作物理地址,那一个程序写错了地址,整个系统就崩了。有了MMU,每个进程都有自己的页表,互相隔离,谁也碰不到谁的数据。

避坑指南:我曾经在调试一个DMA驱动时,发现数据总是写到错误的地方。查了两天才发现,是页表映射没更新。DMA用的是物理地址,而驱动里传的是虚拟地址。记住:DMA操作一定要用物理地址!

1.3 用户空间与内核空间:两个世界,一条界限

在Linux中,虚拟地址空间被划分为两部分:用户空间和内核空间。以32位系统为例,通常的划分是:

区域 地址范围 权限 用途
用户空间 0x00000000 - 0xBFFFFFFF 用户态可读写 应用程序代码、数据、堆栈
内核空间 0xC0000000 - 0xFFFFFFFF 仅内核态可访问 内核代码、驱动、页表

这个划分有什么意义?说白了,就是“隔离”和“保护”。用户程序不能直接访问内核空间,否则一个bug就能把整个系统搞死。我见过不少新手写驱动时,直接在用户态访问内核地址,结果就是段错误。

嗯,这里要注意:64位系统的划分方式不同,但原理是一样的。内核空间在高地址,用户空间在低地址,中间有一条“红线”隔开。

1.4 知识体系全景图

为了让你更直观地理解这些概念之间的关系,我画了一张图:

Linux内存管理全景图 用户空间 虚拟地址:0x0000 - 0xBFFF 权限:用户态可读写 内容:应用代码、数据、堆栈 每个进程独享自己的用户空间 内核空间 虚拟地址:0xC000 - 0xFFFF 权限:仅内核态可访问 内容:内核代码、驱动、页表 所有进程共享同一个内核空间 系统调用 MMU(内存管理单元) 负责将虚拟地址翻译为物理地址 页表 记录虚拟页面到物理页面的映射关系 查询

这张图把咱们刚才讲的内容串起来了。你看,用户空间和内核空间通过系统调用交互,而MMU和页表则负责把虚拟地址翻译成物理地址。整个体系环环相扣,缺一不可。

1.5 实际开发中的体会

我个人习惯在写驱动时,先画一张内存映射图。把虚拟地址、物理地址、页表关系都标清楚。这样调试起来会省很多时间。

我记得有一次,一个同事在调试网络驱动时,发现数据包总是丢。查了半天,原来是DMA缓冲区分配在了用户空间,而DMA控制器根本访问不到。嗯,这就是没搞清楚“用户空间 vs 内核空间”的后果。

所以,我的建议是:

  • 写应用层代码:你只需要关心虚拟地址,不用管物理地址。
  • 写内核驱动:你必须时刻清楚,你操作的是虚拟地址还是物理地址。
  • 写DMA驱动:记住,DMA只认物理地址。用dma_alloc_coherentdma_map_single来获取正确的地址。

警告:千万不要在中断上下文里做复杂的内存操作!我曾经因为在内核中断里调用kmalloc,导致系统死锁。中断上下文只能用GFP_ATOMIC标志,而且分配的内存要尽量小。

好了,这一章的内容就到这里。内存管理是Linux内核的基石,理解透彻了,后面学DMA、设备驱动都会轻松很多。


专注资料整理