《Linux内核设计的艺术》
qq308845474
这个作者很懒,什么都没留下…
展开
-
1.3.5 head.s开始执行(1)
1.3.5 head.s开始执行(1)在讲解head程序之前,我们先介绍一下从bootsect到main函数执行的整体技术策略。在执行main函数之前,先要执行三个由汇编代码生成的程序,即bootsect、setup和head。之后,才执行由main函数开始的用C语言编写的操作系统内核程序。前面我们讲过,第一步:加载bootsect到0x07C00,然后复制到0x90000转载 2015-10-03 11:25:37 · 403 阅读 · 0 评论 -
1.2.2 加载第二部分代码—setup(2)
1.2.2 加载第二部分代码—setup(2)此前的0x07C00这个位置是根据“两头约定”和“定位识别”而确定的。从现在起,操作系统已经不需要完全依赖BIOS,可以按照自己的意志把自己的代码安排在内存中的某个位置了。点评jmpi go, INITSEG go: mov ax, cs 这两行代码写得很巧。bootsect复制完成后,在内存的0x07C00和0x9000转载 2015-10-03 07:45:21 · 426 阅读 · 0 评论 -
1.3.1 关中断并将system移动到内存地址起始位置0x00000
1.3 开始向32位模式转变,为main函数的调用做准备接下来操作系统要使计算机在32位保护模式下工作。这期间要做大量的重建工作,并且持续工作到操作系统的main函数的执行过程中。在本节中,操作系统执行的操作包括打开32位的寻址空间、打开保护模式、建立保护模式下的中断响应机制等与保护模式配套的相关工作、建立内存的分页机制,以及做好调用main函数的准备。1.3.1 关中断并将sys转载 2015-10-03 08:00:05 · 546 阅读 · 0 评论 -
1.2.2 加载第二部分代码—setup(1)
1.2.2 加载第二部分代码—setup(1)1. bootsect对内存的规划现在,BIOS已经把bootsect(也就是引导程序)载入内存了,它的作用就是把第二批和第三批程序陆续加载到内存中。为了把第二批和第三批程序加载到内存中的适当位置,bootsect首先做的工作就是规划内存。通常,我们是用高级语言编写应用程序,这些程序是在操作系统的平台上运行的。我们只管写高级语言转载 2015-10-03 07:36:43 · 390 阅读 · 0 评论 -
1.2.3 加载第三部分代码—system模块(2)
1.2.3 加载第三部分代码—system模块(2)现在,bootsect程序的任务都已经完成!下面要通过执行“jmpi 0, SETUPSEG”这行语句跳转至0x90200处,就是前面讲过的第二批程序—setup程序加载的位置。CS:IP指向setup程序的第一条指令,意味着由setup程序接着bootsect程序继续执行。图1-14形象地描述了跳转到setup程序后的起始状态,转载 2015-10-03 07:56:53 · 348 阅读 · 0 评论 -
1.3.2 设置中断描述符表和全局描述符表
1.3.2 设置中断描述符表和全局描述符表setup程序继续为保护模式做准备,此时要通过setup程序自身提供的数据信息对中断描述符表寄存器IDTR和全局描述符表寄存器GDTR进行初始化设置。小贴士GDT(Global Descriptor Table,全局描述符表):它是系统中唯一存放段寄存器内容(段描述符)的数组,配合程序进行保护模式下的段寻址。它在操作系统的进程切换中转载 2015-10-03 10:28:46 · 1394 阅读 · 0 评论 -
1.3.3 打开A20,实现32位寻址
1.3.3 打开A20,实现32位寻址下面的动作是标志性的—打开A20!打开A20,意味着CPU可以进行32位寻址,最大寻址空间为4GB,注意看图1-19中内存条范围的变化。从5个F扩展到8个F,即0xFFFFFFFF—4GB。 图1-19 打开A20现在看来,Linux 0.11还显得有些稚嫩,最大只能支持16MB的物理内存,但是其转载 2015-10-03 10:32:19 · 419 阅读 · 0 评论 -
2.9.3 设置系统调用总入口
2.9.3 设置系统调用总入口将系统调用处理函数system_call与 int 0x80中断描述符表挂接。system_call是整个操作系统中系统调用软中断的总入口。所有用户程序使用系统调用,产生int 0x80软中断后,操作系统都是通过这个总入口找到具体的系统调用函数。该过程如图2-23所示。 系统调用函数是操作系统对用户程序的基本支持转载 2015-10-18 23:21:00 · 386 阅读 · 0 评论 -
目录
《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》关于Linux内核的书已经不计其数,但这本书却是独树一帜的,它的内容代表着Linux内核研究成果的世界顶尖级水平,它在世界范围内首次提出并阐述了操作系统设计的核心指导思想——主奴机制,这是所有操作系统研究者的一笔宝贵财富。本节为目录部分。AD:目录本书导读前言第1章 从开机转载 2015-10-03 07:17:54 · 355 阅读 · 0 评论 -
1.3.4 为在保护模式下执行head.s做准备
1.3.4 为在保护模式下执行head.s做准备为了建立保护模式下的中断机制,setup程序将对可编程中断控制器8259A进行重新编程。小贴士8259A中断控制器:8259A是专门为了对8085A和8086/8088进行中断控制而设计的芯片,它是可以用程序控制的中断控制器。单个的8259A能管理8级向量优先级中断。在不增加其他电路的情况下,最多可以级联成64级的向量优先级中转载 2015-10-03 10:41:44 · 387 阅读 · 0 评论 -
1.1.2 BIOS在内存中加载中断向量表和中断服务程序
1.1.2 BIOS在内存中加载中断向量表和中断服务程序BIOS程序的代码量并不大,却非常精深,需要对计算机的整个硬件体系结构非常熟悉才能将其看明白。要想把BIOS是如何运行的讲清楚,也得写很厚一本书,这显然超出了本书的主题和范围。我们的主题是操作系统,所以只会将与启动操作系统有直接关系的内容讲解一下。BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。通常,不同的主机板所转载 2015-10-03 07:25:08 · 1497 阅读 · 0 评论 -
1.2.3 加载第三部分代码—system模块(1)
1.2.3 加载第三部分代码—system模块(1)第二批代码已经载入内存,现在要加载第三批代码。仍然是使用BIOS提供的int 0x 13h中断,如图1-11所示,方法与图1-9所示的方法基本相同。 图1-11 再次调用int 0x 13h中断接下来bootsect程序就要执行第三批程序的载入工作,即将系统模块载入内存。从底层技术上转载 2015-10-03 07:49:51 · 373 阅读 · 0 评论 -
linux内核分析之system_call.s
1. 系统调用处理底层程序,通过int 0x80进行系统调用2. 时钟,硬盘,软盘中断处理程序信号,子进程结束SIG_CHLD = 17定义了从系统调用返回时各个寄存器在堆栈中的偏移值(ret_from_sys_call)EAX = 0x00EBX = 0x04ECX = 0x08EDX = 0x0CFS = 0x10ES = 0转载 2015-10-20 21:48:57 · 960 阅读 · 0 评论 -
1.3.5 head.s开始执行(6)
1.3.5 head.s开始执行(6)执行代码如下://代码路径:boot/head.s xorl %eax,%eax /* pg_dir is at 0x0000 */ movl %eax,%cr3 /* cr3-page directory start */ movl %cr0,%eax orl $0x80000000,%eax转载 2015-10-07 18:23:47 · 399 阅读 · 0 评论 -
1.3.5 head.s开始执行(3)
1.3.5 head.s开始执行(3)代码如下://代码路径:boot/head.s setup_gdt ............ setup_gdt: lgdt gdt_descr ret _gdt: .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x00c09a0000000fff转载 2015-10-07 18:16:48 · 353 阅读 · 0 评论 -
1.3.5 head.s开始执行(2)
1.3.5 head.s开始执行(2)小贴士取段寄存器指令(Load Segment Instruction):该组指令的功能是把内存单元的一个“低字”传送给指令中指定的16位寄存器,把随后的一个“高字”传给相应的段寄存器(DS、ES、FS、GS和SS)。其指令格式如下:LDS/LES/LFS/LGS/LSS Reg, Mem 指令LDS(Load Data Seg转载 2015-10-07 18:12:44 · 333 阅读 · 0 评论 -
1.4 本章小结
1.4 本章小结本章的内容主要分为两大部分:第一部分,加载操作系统;第二部分,为32位保护模式和分页模式下的main函数的执行做准备。从借助BIOS将bootsect.s文件加载到内存开始,相继加载了setup.s文件和system文件,从而完成操作系统程序的加载。接下来为32位保护模式和分页模式下的main函数的执行做准备。设置IDT、GDT、页目录表、页表,以及机器系统数据。转载 2015-10-07 18:57:50 · 358 阅读 · 0 评论 -
1.3.5 head.s开始执行(5)
1.3.5 head.s开始执行(5)上述动作的代码如下://代码路径:boot/head.s movl $pg0+7,_pg_dir /* set present bit/user r/w */ movl $pg1+7,_pg_dir+4 /* --------- " " --------- */ movl $pg2+7,_pg_dir+8 /转载 2015-10-07 18:22:56 · 271 阅读 · 0 评论 -
1.1.1 BIOS的启动原理
1.1.1 BIOS的启动原理在了解BIOS是如何将操作系统程序加载到内存中之前,我们先来了解一下BIOS程序自身是如何启动的。从我们使用计算机的经验得知:要想执行一个程序,必须在窗口中双击它,或者在命令行界面中输入相应的执行命令。从计算机底层机制上讲,这其实是在一个已经运行起来的操作系统的可视化界面或命令行界面中执行一个程序。但是,在开机加电的一瞬间,内存中什么程序也没有,没有任何程序在转载 2015-10-03 07:23:12 · 824 阅读 · 1 评论 -
2.7 与建立人机交互界面相关的外设的中断服务程序挂接
2.7 与建立人机交互界面相关的外设的中断服务程序挂接Linus在操作系统源代码中本来设计了chr_dev_init()函数,明显是要用这个函数初始化字符设备,但我们可以看到这是一个空函数。Linus又设计了tty_init()函数,内容就是初始化字符设备。有人解释tty是teletype。字符设备的初始化为进程与串行口(可以通信、连接鼠标……)、显示器以及键盘进行I/O通信准备工转载 2015-10-18 20:27:39 · 363 阅读 · 0 评论 -
2.5 异常处理类中断服务程序挂接(1)
2.5 异常处理类中断服务程序挂接(1)不论是用户进程还是系统内核都要经常使用中断或遇到很多异常情况需要处理,如CPU在参与运算过程中,可能会遇到除零错误、溢出错误、边界检查错误、缺页错误……免不了需要“异常处理”。中断技术也是广泛使用的,系统调用就是利用中断技术实现的。这些中断、异常都需要具体的服务程序来执行。trap_init()函数将中断、异常处理的服务程序与IDT进行挂接,逐步重建转载 2015-10-18 20:18:17 · 664 阅读 · 0 评论 -
2.6 初始化块设备请求项结构
2.6 初始化块设备请求项结构Linux 0.11将外设分为两类:一类是块设备,另一类是字符设备。块设备将存储空间等分为若干同样大小的称为块的小存储空间,每个块有块号,可以独立、随机读写。硬盘、软盘都是块设备。字符设备以字符为单位进行I/O通信。键盘、早期黑屏命令行显示器都是字符设备。进程要想与块设备进行沟通,必须经过主机内存中的缓冲区。请求项管理结构request[32]就是操作转载 2015-10-18 20:20:28 · 386 阅读 · 0 评论 -
2.7.2 对显示器进行设置
2.7.2 对显示器进行设置根据机器系统数据提供的显卡是“单色”还是“彩色”来设置配套信息。由于在Linux 0.11那个时代,大部分显卡器是单色的,所以我们假设显卡的属性是单色EGA。那么显存的位置就要被设置为0xb0000~0xb8000,索引寄存器端口被设置为0x3b4,数据寄存器端口被设置为0x3b5,再将显卡的属性——EGA这三个字符,显示在屏幕上。另外,再初始化一些用于滚屏的变转载 2015-10-18 20:43:33 · 327 阅读 · 0 评论 -
2.8 开机启动时间设置
2.8 开机启动时间设置开机启动时间是大部分与时间相关的计算的基础。操作系统中一些程序的运算需要时间参数;很多事务的处理也都要用到时间,比如文件修改的时间、文件最近访问的时间、i节点自身的修改时间等。有了开机启动时间,其他时间就可据此推算出来。具体执行步骤是:CMOS是主板上的一个小存储芯片,系统通过调用time_init()函数,先对它上面记录的时间数据进行采集,提取不同等级的时转载 2015-10-18 20:59:55 · 349 阅读 · 0 评论 -
2.9 初始化进程0
2.9 初始化进程0进程0是Linux操作系统中运行的第一个进程,也是Linux操作系统父子进程创建机制的第一个父进程。下面讲解的内容对进程0能够在主机中正常运算的影响最为重要和深远,主要包含如下三方面的内容。1)系统先初始化进程0。进程0管理结构task_struct的母本(init_task = {INIT_TASK,})已经在代码设计阶段事先设计好了,但这并不代表进程0已经可转载 2015-10-18 21:07:14 · 377 阅读 · 0 评论 -
2.1 设置根设备、硬盘
第2章 设备环境初始化及激活进程0从现在开始执行main()函数!系统达到怠速状态前所做的一切准备工作的核心目的就是让用户程序能够以“进程”的方式正常运行。能够实现这一目的的标准包括三方面的内容:用户程序能够在主机上进行运算,能够与外设进行交互,以及能够让用户以它为媒介进行人机交互。本章讲解的内容就是为了实现这个目标,对设备环境进行初始化,并激活第一个进程——进程0。Lin转载 2015-10-18 16:39:19 · 443 阅读 · 0 评论 -
2.10 初始化缓冲区管理结构
2.10 初始化缓冲区管理结构缓冲区是内存与外设(如硬盘,以后以硬盘为例)进行数据交互的媒介。内存与硬盘最大的区别在于,硬盘的作用仅仅是对数据信息以很低的成本做大量数据的断电保存,并不参与运算(因为CPU无法到硬盘上进行寻址),而内存除了需要对数据进行保存以外,更重要的是要与CPU、总线配合进行数据运算。缓冲区则介于两者之间,它既对数据信息进行保存,也能够参与一些像查找、组织之类的间接、辅转载 2015-10-18 23:25:11 · 430 阅读 · 0 评论 -
2.4 内存管理结构mem_map初始化
2.4 内存管理结构mem_map初始化对主内存区起始位置的重新确定,标志着主内存区和缓冲区的位置和大小已经全都确定了,于是系统开始调用mem_init()函数。先对主内存区的管理结构进行设置,该过程如图2-5所示。具体执行代码如下://代码路径:init/main.c: void main(void) { … mem_init(main转载 2015-10-18 20:17:42 · 2262 阅读 · 0 评论 -
2.7.1 对串行口进行设置
2.7.1 对串行口进行设置把两个串行口中断服务程序与IDT相挂接,然后根据tty_table数据结构中的内容对这两个串行口进行初始化设置,包括设置线路控制寄存器的DLAB 位、设置发送的波特率因子、设置DTR和RTS……最后,允许主8259A 芯片的IRQ3和IRQ4 发送中断请求。挂接的具体过程及挂接后的效果如图2-13所示。执行代码如下://代码路径:ke转载 2015-10-18 20:29:49 · 492 阅读 · 0 评论 -
2.9.1 初始化进程0
2.9.1 初始化进程0sched_init函数比较难理解的是下面两行:set_tss_desc(gdt?+?FIRST_TSS_ENTRY,&(init_task.task.tss));set_ldt_desc(gdt?+?FIRST_LDT_ENTRY,&(init_task.task.ldt));这两行代码的目的就是要像图2-17表现的那样在GDT中初始化进程转载 2015-10-18 21:28:14 · 436 阅读 · 0 评论 -
2.2 规划物理内存格局,设置缓冲区、虚拟盘、主内存
2.2 规划物理内存格局,设置缓冲区、虚拟盘、主内存接下来设置缓冲区、虚拟盘、主内存。主机中的运算需要CPU、内存相互配合工作才能实现,内存也是参与运算的重要部件。对内存中缓冲区、主内存的设置、规划,从根本上决定了所有进程使用内存的数量和方式,必然会影响到进程在主机中的运算速度。具体规划如下:除内核代码和数据所占的内存空间之外,其余物理内存主要分为三部分,分别是主内存区、缓冲区和虚转载 2015-10-18 20:16:37 · 684 阅读 · 0 评论 -
2.5 异常处理类中断服务程序挂接(2)
2.5 异常处理类中断服务程序挂接(2)对比:set_trap_gate(0,÷_error) set_trap_gate(n,addr) _set_gate(&idt[n],15,0,addr) _set_gate(gate_addr,type,dpl,addr) 可以看出,n是0;gate_addr是&idt[0],也就是idt的第一项中断描述符转载 2015-10-18 20:19:44 · 399 阅读 · 0 评论 -
2.7.3 对键盘进行设置
2.7.3 对键盘进行设置对键盘进行设置是先将键盘中断服务程序与IDT相挂接,然后取消8259A中对键盘中断的屏蔽,允许IRQ1发送中断信号,通过先禁止键盘工作、再允许键盘工作,键盘便能够使用了。键盘中断处理程序与IDT的挂接函数set_intr_gate()与前面讲解过的set_trap_gate()函数类似,参看对set_trap_gate()函数的讲解。效果如图2-15所示。转载 2015-10-18 20:50:47 · 359 阅读 · 0 评论 -
2.9.2 设置时钟中断
2.9.2 设置时钟中断接下来就对时钟中断进行设置。时钟中断是进程0及其他由它创建的进程轮转的基础。对时钟中断进行设置的过程具体分为如下三个步骤。1)对支持轮询的8253定时器进行设置。这一步操作如图2-20中的第一步所示,其中LATCH最关键。LATCH是通过一个宏定义的,通过它在sched.c中的定义“#define LATCH (1193180/HZ)”,即系统每10毫秒发生转载 2015-10-18 23:17:50 · 592 阅读 · 0 评论 -
1.2.1 加载第一部分代码—引导程序(bootsect)
1.2 加载操作系统内核程序并为保护模式做准备从现在开始就要执行真正的boot操作了,即把软盘中的操作系统程序加载至内存。对于Linux 0.11操作系统而言,计算机将分三批逐次加载操作系统的内核代码。第一批由BIOS中断int 0x19h把第一扇区bootsect的内容加载到内存;第二批和第三批在bootsect的指挥下,分别把其后的四个扇区和随后的240个扇区的内容加载至内存。转载 2015-10-03 07:28:21 · 595 阅读 · 0 评论 -
1.1 启动BIOS,准备实模式下的中断向量表和中断服务程序
《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》第1章从开机加电到执行main函数之前的过程,本章的内容主要分为两大部分:第一部分,加载操作系统;第二部分,为32位保护模式和分页模式下的main函数的执行做准备。本节为大家介绍启动BIOS,准备实模式下的中断向量表和中断服务程序。AD:第1章 从开机加电到执行main函数之前的过程转载 2015-10-03 07:22:22 · 1310 阅读 · 0 评论 -
2.3 设置虚拟盘空间并初始化
2.3 设置虚拟盘空间并初始化接下来将对外设中的虚拟盘区进行设置。检查makefile文件中“虚拟盘使用标志”是否设置,以此确定本系统是否使用了虚拟盘。我们设定本书所用计算机有16 MB的内存,有虚拟盘,且将虚拟盘大小设置为2 MB。操作系统从缓冲区的末端起开辟2 MB内存空间设置为虚拟盘,主内存起始位置后移2 MB至虚拟盘的末端。图2-3展示了设置完成后的物理内存的规划格局。转载 2015-10-18 20:17:09 · 837 阅读 · 0 评论 -
1.3.5 head.s开始执行(4)
1.3.5 head.s开始执行(4)确定A20地址线已经打开之后,head程序如果检测到数学协处理器存在,则将其设置为保护模式工作状态,图1-33给出了示意。 图1-33 检测数学协处理器小贴士x87协处理器:为了弥补x86系列在进行浮点运算时的不足,Intel于1980年推出了x87系列数学协处理器,那时还是一个外置的、可选的芯片转载 2015-10-07 18:21:14 · 462 阅读 · 0 评论