linux内核

(以下内容是我目前的理解,可能有不对的地方)


计算机加电开机后,BIOS会把启动盘的0磁道0扇区的前512字节加载到0x7c00处(这个加载过程是bios负责的,操作系统不用管),然后从这开始运行,这512字节一般称为引导程序(bootsect.S),它负责把操作系统程序加载到内存0x10000处(这个加载是用bios中断实现的,中断向量表在0x0地址处,所以不能直接拷贝到0x0处),然后拷贝到0x0处,然后进入保护模式,然后跳转到0x0处开始运行。
linux内核


在进入保护模式之前是实模式,两者寻址方式不同:
实模式地址直接给出:段地址<<4 + 偏移地址,反正就是给两个地址,一个地址左移4位加上另一个地址就是实际的地址了。

保护模式寻址就涉及GDT,GDT是一个数组,每项占8个字节,指定了一段内存,包括内存基地址,这段内存是干什么的,段限长,特权级等等。现在要访问一个地址,就不能直接给两个地址组合一下了,要指定GDT中的一项,这就给出了段基地址,然后指定段偏移,这两者相加,就是实际地址了。

如果开启了分页查询,上面得到的32位地址,还要根据页目录和页表再变换一下,才能得到实际物理地址。


操作系统除了开始bootsect.S是在实模式下运行,剩下的都是运行在保护模式,保护模式所有的段都要在GDT中定义,不能直接访问一个内存地址,所以可以根据GDT了解操作系统。

赵炯老师的《Linux内核完全剖析》第4章最后实现了一个简单的多任务内核实例,两个任务交替在时钟中断下交替运行,一个任务打印A,一个任务打印B。


在这里说下任务(进程)在内核中是怎么表示的,任务是有数据段、代码段(数据段、代码段由LDT指定,LDT和GDT差不多,不过GDT是整个内核公用的,LDT是一个任务一个,指定了这个任务的代码段,数据段)、堆栈段(又分为内核栈、用户栈),任务运行时是要用到各个寄存器的。

表示任务的数据结构是:任务状态段TSS,这是一个段,放在内存中,里面存放了通用寄存器、标志寄存器的值,还有LDT选择符,不同特权级的堆栈(SS、ESP),还有前一个任务的链接(TSS选择符)。

这样一个数据结构就可以完整的表示一个任务了。


所以上面简单的多任务内核,首先有内核代码段、内核数据段,两个任务,每个任务一个TSS,一个LDT。
linux内核


linux内核

参考:
赵炯《Linux内核完全剖析——基于0.12内核》
于渊《ORANGE’S:一个操作系统的实现》
Randal E.Bryant David R.O’Hallaron《深入理解计算机系统》
王爽《汇编语言》
void的视频
郑州大学 汇编语言程序设计
国防科技大学 计算机原理
哈尔滨工业大学 *军老师 操作系统

http://down.51cto.com/zt/6417/1(没有看)