4月14日
很多硬件的功能,物尽其用却未必好过软实现,Linux出于可移植性及其它原因,常常选择不去过分使用硬件特性。
比如 Linux只使用四个segment,分别是__USER_CS、__USER_DS、__KERNEL_CS、__KERNEL_DS,因为Paging可以完成segmentation的工作,而且可以完成的更好。而且这样简化了很多,统一了逻辑地址和线性地址。
而TSS存在每CPU一个的GDT中,虽然每个process的TSS不同,但Linux 2.6却不利用其中的hardware context switch(虽然低版本使用)以一个far jmp来实现任务转换,而用一系列的mov指令来实现。这样做的原因是:
1、可以检验ds和es的值,以防恶意的forge。
2、硬转换和软转换所用时间相近,而且硬转换是无法再优化的,软转换则可以。
4月15日
Paging也就是将linear地址转成物理地址的机制。
内存被视为一堆4k的小page frame(就像空的格子),在归OS管的Paging机制的苟延残喘下,仿佛地存放着多于page frame数目的page(数据)。要通过两层索引(directroy和table)来寻到page,再加offset寻到址。这两层索引中的entry包含一些标志表明该page在不在内存里,是否被改写过,最近是否访问过,以及读/写访问权限。
如果page entry里的Page Size标志和cr4的PSE标志设置了的话(Extended Paging),就是4M一片page frame,这样就只用directory一层索引了。
从奔腾pro开始,adress针脚非常神奇地从32增加到36,有了一个叫做PAE的机制,它启用(cr4的PAE标志设置)的时候就是2M一片page frame了。这样可以寻址64GB,远远超越了没启用前4GB的理论极限(实际极限1GB)。但这样的寻址非常别扭,因为物理地址虽然因此变成了36位,线性地址仍是32位,要想寻址超过4GB,要用cr3去指向不同的PDPT或在31-30bit指定PDPT中entry。不过,更郁闷的是,这并不能改变process的地址空间4GB的限制,仅仅是内核可以用这么多内存来运行更多的process。
在64位机器上,由于如果只用两层的话,索引条目会太多,严重消耗内存,所以只好再加层数,alpha、ia64、ppc64、sh64都是3层(虽然每层bit数不一),x86_64非常神奇地用了4层。
Paging换的是page,Cache换的是line。但是如何在Cache中确定某个内存地址在不在呢?或者说,某内存地址附近的数据,放在Cache中什么位置好呢?不能一对一映射过来(direct mapping),这样会导致巨大的Cache;也不能随意放(fully associative)然后在旁边标记(tag)说是什么地址附近的,这样会导致每次找Cache都是线性查找。一个浪费空间一个浪费时间,因此有一种折衷叫做N-Way Set Associative,有点像Hash。首先把Cache分成很多个N line的集合,然后弄个hash函数把一个地址唯一地映射到某个集合里,之后至于放在这N line中的哪一line就无所谓了。找的时候,先一瞬间找到集合,然后对N line进行线性查找。
读的时候,自然有cache hit和cache miss。对于写操作,cache hit的话,可能有两种不同的处理方法:write-through(Cache和RAM都写)和wirte-back(line换出时写RAM)。Linux清空PCD
(Page Cache Disable)和PWT
(Page Write-Through),永远启用cache并使用write-back策略。
哈哈,TLB(Translation Lookaside Buffers )解决了我心中的一大疑问:每次寻址(将linear翻译成physical),都要非常艰辛地查directroy和table,访问多次RAM(你以为这些东西不是放在RAM里啊?!),岂不累死。幸好,我们有TLB,这样最近翻译的成果就可以缓存在里面,这样就省得每次翻译啦。
4月17日
Linux用了四层索引来做Paging。这样既可以通过隐藏掉中间两层来做无PAE的32位paging,又可以隐藏掉pud来支持有PAE的3位paging,还可以支持64位的paging。
pte_t Page Table
pmd_t Page Middle Directory
pud_t Page Upper Directory
pgd_t Page Global Directory
每个进程的内存空间中0到PAGE_OFFSET(0xc0000000,即3G)-1是用户空间,PAGE_OFFSET到0xffffffff(4G)则是内核空间(只有内核态才能寻址)。
启动的时候,Linux问BIOS内存格局如何,保留第1个MB(machine_specific_memory_setup()),然后把自己放在第2个MB开始的地方(从_text到_etext是内核代码,从_etext到_edata是初始化了的内核数据)。
在这个过程中:
Linux首先建立初始(provisional)页表(startup_32()),使RAM前8M(两页)可以用两种方式寻址,用来存放最小的自己(text、data、初始页表、128k的堆空间)。
初始pgd放在swapper_pg_dir中。所有项为0,但0、1与0x300、0x301分别完成线性地址的前8M和3G+8M到物理地址前8M的映射。
接着,Linux建立最终页表。
线性地址最高的128M保留给Fix-Mapped Linear Addresses和Noncontiguous Memory Allocation用,所以,最终页表只需要把PAGE_OFFSET后面的896M映射到物理地址的前896M。剩余RAM由Dynamic Remapping来完成。然后用zap_low_mapping()把原先那个初始页表清掉。
paging_init()会执行:
pagetable_init() //一个循环,初始化了swapper_pg_dir
cr3 <- swapper_pg_dir
cr4 |= PAE
__flush_tlb_all()
Linux利用CPU有限的指令和行为模式,实现了一系列操纵tlb的函数,应用于不同的情境。
值得一记的是Lazy TLB模式,在多CPU系统中,它可以避免无意义的TLB刷新。
分享到:
相关推荐
Linux 2.6内核下的USB热插拔机制实现了设备的动态管理,极大地方便了用户的使用。通过对USB设备的热插拔流程进行深入分析,我们可以了解到这种机制不仅适用于USB设备,也适用于其他类型的PNP设备,如SD卡、PCMIA卡和...
Linux内核配置是定制操作系统...总的来说,Linux 2.6内核配置是一个复杂而细致的过程,需要根据系统的需求和硬件特性谨慎选择。每个选项都有其特定的作用,理解这些选项的含义有助于创建一个高效、稳定且定制化的内核。
通过阅读和研究这个中文注释版的源码,开发者不仅可以了解Linux内核的基本结构,还能深入理解其内部机制,如调度器的工作方式、内存管理的策略、文件系统的实现、网络协议栈的流程等。这对于系统级编程、驱动开发...
Linux 2.6内核对电源管理的休眠支持主要涉及两种电源管理标准:APM(Advanced Power Management)和ACPI(Advanced Configuration and Power Interface)。APM是早期的电源管理技术,由BIOS控制,虽然提供了CPU和...
在Linux 2.6内核版本中,设备驱动的编写和管理有了更高效和灵活的方法。这篇笔记主要针对的是Linux 2.6.10及以后内核版本的设备驱动开发,特别是基于《Linux Device Driver3》这本书中的scull设备驱动示例。 首先,...
《2.6内核配置手册》是针对软件开发人员的重要参考资料,主要涵盖了Linux内核配置的各种选项和设置,以满足不同需求和环境。内核配置是定制化内核的关键步骤,直接影响系统的性能、稳定性和功能。 1. **代码成熟度...
/sys 是 linux2.6 内核的一个大的变化,该目录下安装了 2.6 内核中新出现的一个文件系统 sysfs /temp 存放一些临时文件 /dev 类似于 windows 的设备管理器,把所有的硬件用文件的形式存储 /media linux 系统会自动...
内核启动后,会进一步初始化内存管理系统,包括: - 设置内存页表。 - 初始化伙伴系统和ZONE结构。 - 配置和优化缓存机制。 ##### 2.3 Bitmap的初始化 Bitmap是一种数据结构,用于表示内存页的状态(如已分配、...
这包括CPU的初始化代码、中断控制器、内存管理单元(MMU)、GPIO、时钟管理、电源管理等。 在移植过程中,第一步通常是获取Linux源代码。你可以从Linux官方网站下载对应版本的源码,或者从特定的分支或维护者那里...
另外,作者根据自己反复阅读linux2.6内核源代码和linux内核参考书的笔记与心得,用很大篇幅深入剖析了linux内核的组成结构以及各组件的实现原理,在阐述理论的同时对内核源代码进行详细注释,这样既加深了对linux...
另外,作者根据自己反复阅读linux2.6内核源代码和linux内核参考书的笔记与心得,用很大篇幅深入剖析了linux内核的组成结构以及各组件的实现原理,在阐述理论的同时对内核源代码进行详细注释,这样既加深了对linux...
Linux 2.6内核学习笔记本仓库已经开始作为gitbook仓库,访问地址 GitHub访问地址 Something I hope you know before go into the coding~First, please watch or star this repo, I'll be more happy if you follow ...
- **移植多媒体播放器MPlayer**:提供了移植MPlayer到Linux 2.6内核的具体步骤。 - **移植YAFFS文件系统**:介绍了移植YAFFS文件系统的尝试过程。 - **处理NAND ECC问题**:探讨了与NAND ECC相关的常见问题及其解决...
本文旨在详细介绍如何将Linux 2.6.22.2内核移植到友善之臂SBC2440V4开发板上,特别关注双网卡的支持。友善之臂SBC2440V4是一款基于ARM920T内核的S3C2440处理器的开发板,具有较高的性价比和广泛的用途。本篇文档不仅...
### Linux内核编译知识点详解 #### 一、编译环境准备 在开始编译Linux内核之前,首先需要确保你的开发环境满足以下条件: 1. **下载内核源码**:可以从官方网址(`http://www.kernel.org/pub/linux/kernel/v2.6/`...
Linux 2.6.24 内核注解 增加了mtd层的注解,顺带引出了block文件夹中的注解 若代码和头文件中注解有不一致的,以头文件的注解为准, 因为都是一边看一边加注的,经常会出现第一次理解不对的情况,而后的修改,再...
《升级,感受Linux新时空》这篇文档主要讨论的是Linux操作系统中的一个重要更新——2.6内核的升级及其带来的新特性。Linux 2.6内核的发布标志着Linux系统的一个重大进步,尤其在服务器领域表现出色,但对于桌面电脑...
arm部分: s3c2440的linux2.6内核移植所需修改的代码,代码都是直接从内核源代码修改 的。所以请遵守GNU通用公共许可证 一些随手记录的东西 还有一些技术名词和概念的解释 网上收集: 一些我在网上收集的一些...