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