2011年7月13日星期三

Linux 0.11 内核完全注释 笔记(一)

有人说:”初恋不懂爱情!“。的确,五年前我读了《Linux 0.11 内核完全注释》一书,茫然的看完,悄然的离去。所幸的是种下了一个Idea:“这书还是不错的。”

五年后,再读此书,感触颇多,当读到move_to_user_mode这个神器时不由自主在weibo上像文人骚客一样发出如下感叹:

”一生至少该有一次,为了某段代码而陶醉自己,不求年代,不求国籍,不求编程语言,甚至不求编译运行,只求在我思索的年华里,遇到你。“
http://oldlinux.org/lxr/http/source/include/asm/system.h#L1

言归正传,笔记开始!

写操作系统不读CPU手册和上厕所不带纸是一个概念,不是扯淡就是高手!所以此书上来先介绍了X86保护模式编程的东东,只有弄清楚这些东东,才能9浅1深的去理解Kernel。X86的保护模式编程个人感觉还是挺复杂的,毕竟要游走于N多概念之间。

Q1 逻辑地址如何转换到物理地址?

Logical Address (逻辑地址)
Linear Address (线性地址)
Physical Address (物理地址)

这些是地址,我们的程序编译完的地址可以粗略理解成逻辑地址,在开启保护模式的情况下,CPU在指令运算时,都需要把程序的逻辑地址转换到真实的物理地址上。怎么转换?靠查表!怎么查?要查表首先要知道表在哪里,然后要知道表的Index,进而得到表项,得到表项后再分析就可以得到真实的物理地址。顺藤摸瓜也!Intel的X86 CPU已经把藤和瓜所需的数据结构都准备好了。

Local Descriptor Table (局部描述符表)LDT
Gloal Descriptor Table (全局描述符表)GDT
Local Descriptor Table Register (局部描述符表寄存器)LDTR
Gloal Descriptor Table Register (全局描述符表寄存器)GDTR
LDT/GDT是表,表的线性地址放在了LDTR/GDTR寄存器中,这是“藤1”。


Code Segment Selector (代码断选择符) CS
Data Segment Selector (数据段选择符) DS
Stack Segment Selector (堆栈段选择符) SS
{C|D|S}S这些是段选择符,Bit2标识使用GDT or IDT,bit3~15是Index信息,这是“藤2”。

Code Segment Descriptor (代码段描述符)
Data Segment Descriptor (数据段描述符)
System Segment Descriptor (系统段描述符)
系统断描述符又可分为:
1 LDT段描述符
2 TSS(Task State Segment)描述符
3 中断门描述符
4 调用门描述符
5 任务门描述符
6 陷阱门描述符
LDT/GDT中的表项就是这些{断|门}描述符,每个描述符都占用8个Byte空间,这是“藤3”。

所以CPU在逻辑地址转换到物理地址过程中,顺着藤1,藤2,找到了藤3。
找到藤3之后,CPU解剖了藤3,挖出了段基地址,然后与逻辑地址相加,这样就得出线性地址。

在没有开启分页机制情况下,线性地址就是真实的物理地址。如果已经开启分页,那就要再顺着“藤4”去摸。CR3寄存器存放着当前任务使用页目录的物理地址。这是"藤4“。经过分析后直接找到物理地址,顺藤摸瓜结束。

Intel还算厚道,没来个18摸,最多也就是Inception的3重梦境。累了,以后再写!

没有评论: