在linux中,由于段的基数都是0,所以逻辑地址与线性地址重合(《理解linux内核》一书)。我认为不同进程的逻辑地址可能相同,所以不同进程的线性地址可能相同,每个进程查看4GB,每个进程都会有自己的线性地址空间(本地地址空间)。但是其他一些文章说所有进程共享一个很大的线性地址空间,并且使用段机制将不同的进程映射到线性地址空间的不同部分。听起来像是具有更宽地址位的全局线性地址空间。我哪里错了?或者它们用于不同的架构?
2 回答
每个 Linux进程都有自己的地址空间;它是虚拟内存。不同的进程有不同的地址空间(但一个进程内的所有线程共享相同的地址空间)。
您可以通过读取 或从进程内部获取1234
Linux 上的进程图/proc/1234/maps
/proc/self/maps
尝试以下命令
cat /proc/$$/maps
cat /proc/self/maps
并考虑他们的输出;第一个命令显示你的 shell 的内存映射;第二个显示正在运行的进程的内存映射cat
地址空间在程序启动时使用execve(2)设置,并使用mmap(2)和相关的系统调用进行更改。
应用程序仅通过系统调用与内核交互。内核有一个“不同的”地址空间,你不应该关心它(除非你在内核内部编码)。
还可以阅读一本好书,例如Advanced Unix Programming和/或Advanced Linux Programming
另请参阅有关系统调用的说明。
请注意,分段寻址是 i386 特有的并且已过时:大多数系统不再使用它。它在 x86-64 的 64 位模式下完全消失了。所有 Linux 系统都使用平面内存模型
请仔细阅读所有参考资料。
Intel 支持 3 种地址:
逻辑地址——(段单元)——>线性地址——(分页单元)——>物理地址
如您所知,所有内核和用户代码访问数据或文本都认为是虚拟地址(CPU 中的逻辑地址)。地址转换为线性地址如下图:
由于 linux 实现不支持线性寻址的概念,段仅用于权限控制。Linux 内核将每个段的偏移值配置为零。这就是为什么你看不到内核中的线性地址和内核直接在分页单元上使用虚拟地址的原因。
得到线性地址后,MMU 分页单元参考CR3 寄存器,得到调页表的基址,生成物理地址。
与 cpu 缓存相同,分页单元在每个 CPU 内核上也有一个 TLB 缓存,以加快在内存上执行的地址转换。
参考: intel64软件开发者手册