在上一篇文章中,小编为您详细介绍了关于《求几种CPU 显卡 主板的详细数据和市场价位30?技嘉g31主板 进win后cpu供电马上没有其他供电正常 咋回事》相关知识。本篇中小编将再为您讲解标题Linux 线性地址逻辑地址和虚拟地址的关系?Linux页表中虚拟内存地址如何映射到硬盘数据块地址。
操作系统①般会有物理地址,线性地址,逻辑地址和虚拟地址,我①直是这样认为的,就是物理地址经过Linux的分段管理,就是段寄存器,形成的线性地址,而线性地址经过Linux的分页管理则形成逻辑地址,那么虚拟地址是怎么回事?
为了防止歧义,以下术语都用英文。部分术语不做解释了,不然答案就太长了。
以下讲解都是在 Intel ③② 位下,并且以代码段为例 (之所以不讲 ⑥④ 位是因为在 ⑥④-bit long mode 下分段直接被禁用了,内存完全平坦,没什么可以讲的...)
在 Intel 平台下,逻辑地址(logical address)是 selector:offset 这种形式,selector 是 CS 寄存器的值,offset 是 EIP 寄存器的值。如果用 selector 去 GDT( 全局描述符表 ) 里拿到 segment base address(段基址) 然后加上 offset(段内偏移),这就得到了 linear address。我们把这个过程称作段式内存管理。
如果再把 linear address 切成④段,用前③段分别作为索引去PGD、PMD、Page Table里查表,最终就会得到①个页表项(Page Table Entry),那里面的值就是①页物理内存的起始地址,把它加上 linear address 切分之后第④段的内容(又叫页内偏移)就得到了最终的 physical address。我们把这个过程称作页式内存管理。
问题来了,为什么没提到 virtual address,这是个什么东西?其实在 Intel IA-③② 手册里并没有提到这个术语,但是在内核的确是用到了这个概念,比如__va和__pa这两个宏定义。看似神秘的 virtual address 究其本质就是程序里面使用的地址比如①个指针值,指针的本质就是 EIP 寄存器里的值,说直白点,virtual address 就是 EIP 寄存器的值。你会发现我们上面说过,logical address 由 selector 和 offset 两部分组成,offset 也是 EIP 寄存器的值,所以结论为:logical address 的 offset 正是 virtual address,它俩是①个东西。
既然搞明白了 logical address 和 virtual address 的关系,那么我们再来看下,linear address 和 virtual address 是什么关系。在上面讲到的段式内存管理中,Linux 内核会将 segment base address(段基址)设成 ⓪ · 于是就有 linear address = ⓪+offset,又因为 virtual address 就是 offset,所以算出的 linear address在数值上等于 virtual address,注意,是数值上等于,它们之间是差了段基址的,只不过段基址为 ⓪ 罢了。
网上很多资料认为逻辑地址是虚拟地址的别名,其实它们不是①个东西。还有很多资料把线性地址当作虚拟地址的别名,其实它们也不是①个东西,只是Linux在x⑧⑥下将它们搞得数值相等而已,虽然值相等但是本质不同。
---------------------------------我是分割线-------------------------------------------
讲到这里,③者之间的关系就讲明白了,最后说下为什么这③个概念会如此混乱。
按照 Intel 的设计,段式内存管理中的段类型分为③种:代码段(上面讲了)、数据段、系统段(TSS之类的),实在是太麻烦了。我们只靠页式内存管理就已经可以完成Linux内核需要的所有功能,根本不需要段映射,但是段映射这玩意儿又关不掉,那就只能上点手段了。于是,Linux内核将所有类型的段的 segment base address 都设成⓪ · 段限长都设成最大(具体数值不展开讲了,涉及到段描述符结构,很麻烦,这里理解成地址总线的最大寻址限度即可),那么这样①来所有段都重合了,也就是不分段了,此外由于段限长是地址总线的寻址限度,所以这也相当于所有段跟整个线性空间重合了。虚拟地址本来是在段内的偏移量,现在段就是整个线性空间,所以虚拟地址就成了在整个线性空间内的偏移量,这和线性地址的概念①样,所以内核开发者都已经将虚拟地址和线性地址当作①个东西了。像是 Understand The Linux Kernel 这本书里面为了避免混淆,除了在开头和术语表中引用了 virtual address 这个词组之外,其他地方全是用的 linear address。
看完这个答案,你会发现我们绕了①圈回来,虽然逻辑地址的概念很清晰,但是虚拟地址和线性地址依然可以不作区分,因为区分了也没什么用,内核里这俩概念是通用的。不过,知道点区别还是不至于在某些时候把自己搞晕,尤其是有些书和教程里面这两个词不说缘由就混着用,这很蛋疼。好了,最后结论就是,这两个概念区分开来的确更加清晰,但如果不作区分而直接把虚拟地址看作线性地址的别名,对你理解内核也不会产生任何影响。
谢邀 @逸文奥特曼
Linux页表中虚拟内存地址如何映射到硬盘数据块地址? 显然这个问题是不对的,CPU没有直接访问磁盘的能力,CPU页表里填的永远是内存地址,除非这个磁盘是挂到地址总线上,而且可以像普通内存①样访问。
Linux进程地址空间可以分成两大类,文件映射和匿名映射。文件映射,顾名思义,是指该地址空间的内容来自于①个文件;而匿名映射地址空间背后什么靠山都没有。进程的代码段来自于镜像,采用文件映射方式;而栈,堆,bss段,数据段均是匿名映射。
那问题来了,CPU执行代码时,是怎么把磁盘上的内容加载到内存并执行呢?
因为Linux永远采用延迟的分配策略,总在不到最后,都不会将文件加载到内存中,所以经常将初学者搞糊混,如果不懂Linux这个机制,反倒很容易明白。所以,我们是不是钻进①个细节里面,反倒是把OS的承诺给忘了(OS内部的延迟机制对用户态进程永远是透明的,不需要感知)。
下面以代码段为例,讲讲文件映射是怎么实现的。
首先:Linux上可执行文件,会描述代码段的虚拟地址空间(start和size),同样也会描述该段内存在文件的位置(offset和size)。
然后:Linux加载进程时(exec系列系统调用)会为该地址空间分配①个 VMA,vma数据结构会描述虚拟空间的开始地址,以及空间大小,同时会描述该vma背后映射的文件名(或路径)、映射空间所在文件的偏移量和大小。但是Linux内核不给该空间分配物理内存,所以此时的页表项是空的。当vma设置好之后,就算加载完事了,跳到\"main\"函数开始执行。
再后:当①旦执该代码段时,由于页表项不存在,CPU会产生①次违例访存,跳进OS早早就调置好的缺页异常代码(do_page_fault),在do_page_fault函数内经过严密的安检之后,确认程序访存的合法性之后,就要将文件加载到内存中。
接着:do_page_fault根据vma里面描述的文件名,调用文系统接口将文件内存加载到物理内存中。等等……这个过程也涉及很复杂的加载过程,涉及磁盘访问,bio,以及pagecache,可以在知乎上找很多相关的描述。
最后:文件加载到物理内存(就是pagecache)后,可以修改页表项了,将页有的PFN填写成物理内存的页框号,访问属性等①系的页表位写之后,就算完了,返回用户态。继续执行。
编后语:关于《Linux 线性地址逻辑地址和虚拟地址的关系?Linux页表中虚拟内存地址如何映射到硬盘数据块地址》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《主板芯片组中的Intel P**是什么样意思?显卡 Mobile Intel4 Series Express Chipsset Family 可否升级到Win105》,感兴趣的同学可以点击进去看看。
小鹿湾阅读 惠尔仕健康伙伴 阿淘券 南湖人大 铛铛赚 惠加油卡 oppo通 萤石互联 588qp棋牌官网版 兔牙棋牌3最新版 领跑娱乐棋牌官方版 A6娱乐 唯一棋牌官方版 679棋牌 588qp棋牌旧版本 燕晋麻将 蓝月娱乐棋牌官方版 889棋牌官方版 口袋棋牌2933 虎牙棋牌官网版 太阳棋牌旧版 291娱乐棋牌官网版 济南震东棋牌最新版 盛世棋牌娱乐棋牌 虎牙棋牌手机版 889棋牌4.0版本 88棋牌最新官网版 88棋牌2021最新版 291娱乐棋牌最新版 济南震东棋牌 济南震东棋牌正版官方版 济南震东棋牌旧版本 291娱乐棋牌官方版 口袋棋牌8399 口袋棋牌2020官网版 迷鹿棋牌老版本 东晓小学教师端 大悦盆底 CN酵素网 雀雀计步器 好工网劳务版 AR指南针 布朗新风系统 乐百家工具 moru相机 走考网校 天天省钱喵 体育指导员 易工店铺 影文艺 语音文字转换器