操作系统高级教程.docx

上传人:b****1 文档编号:152884 上传时间:2022-10-04 格式:DOCX 页数:8 大小:30.54KB
下载 相关 举报
操作系统高级教程.docx_第1页
第1页 / 共8页
操作系统高级教程.docx_第2页
第2页 / 共8页
操作系统高级教程.docx_第3页
第3页 / 共8页
操作系统高级教程.docx_第4页
第4页 / 共8页
操作系统高级教程.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

操作系统高级教程.docx

《操作系统高级教程.docx》由会员分享,可在线阅读,更多相关《操作系统高级教程.docx(8页珍藏版)》请在冰豆网上搜索。

操作系统高级教程.docx

1.为什么开始启动计算机的时候,执行的是BIOS代码而不是操作系统自身的代码?

计算机启动的时候,内存未初始化,CPU不能直接从外设运行操作系统,所以必须将操作系统加载至内存中,而这个工作最开始的部分,BIOS需要完成一些检测工作,和设置实模式下的中断向量表和服务程序,并将操作系统的引导扇区加载值0x7c00处,然后将跳转至0x7c00。

这些就是由bios程序来实现的。

所以计算机的启动最开始执行的是BIOS代码。

2.为什么BIOS只加载了一个扇区,后续扇区却是由bootsect代码加载?

为什么BIOS没有直接把所有需要加载的扇区都加载?

对于bios来说,“约定”在接到启动操作系统的命令后,“定位识别”只从启动扇区把代码加载到0x7c00这个位置。

后续扇区则由bootsect代码加载,这些代码由编写系统的用户负责,与bios无关。

这样构建的好处就是站在整个体系的高度,统一设计和统一安排,简单而有效。

Bios和操作系统的开发都可以遵循这一约定,灵活地进行各自的设计。

操作系统的开发也可以按照自己的意愿,内存的规划等等都很灵活。

3.为什么BIOS把bootsect加载到0x07c00,而不是0x00000?

加载后又马上挪到0x90000处,是何道理?

为什么不一次加载到位?

(1)因为bios将从0x00000开始的1KB字节构建中断向量表,接着的256K字节内存空间构建了bios数据区,所以不能把bootsect加载到0x00000,0x07c00是bios设置的内存地址,不是bootsect能够决定的。

(2)首先,在启动扇区中会有一些数据,将会被内核利用到。

其次,依据系统对内存的规划,内核终会将占用0x0000其中的空间,因此0x7c00可能被覆盖。

将该扇区挪到0x90000,在setup.s中,获取一些硬件数据保存在0x90000-0x901ff处,可以对一些后面内核将要利用的数据集中保存和管理。

4.bootsect、setup、head程序之间是怎么衔接的?

给出代码证据。

(1)bootsect跳转到setup程序:

jumpi0,SETUPSEG

这句代码跳转到0x90200处,即setup程序加载的位置,CS:

IP指向setup程序的第一条指令,意味着setup开始执行

(2)setup跳转到head程序,CPU工作模式首先转变为保护模式然后执行jumpi0,8

0指的是段内偏移,8是保护模式下的段选择符:

01000,其中两位表示内核特权级,第三位0代表GDT,1表示GDT表中中的内核代码段,段基址为0x00000000,而head程序地址就在这里,意味着head程序开始执行

5.setup程序的最后是jmpi0,8,为什么这个8不能简单的当作阿拉伯数字8看待,究竟有什么内涵?

这里面的8要看作是二进制的1000,最后两位00表示内核特权级,第三位0表示GDT表,第四位1表示所选的表的1项来确定内核代码段的段基址和段线长等信息。

这样我们得到的代码就是从段基址0x00000000偏移为0处开始执行,即head的开始位置。

6.保护模式在“保护”什么?

它的“保护”体现在哪里?

特权级的目的和意义是什么?

分页有“保护”作用吗?

(1)在GDT、LDT及IDT中,均有自己的界限,特权级等属性,这是对描述符所描述的对象的保护

(2)在不同的特权级间访问的时候,系统会对CPL、RPL、DPL、IOPL等进行检验,对不同层级的程序进行保护,还限制某些特殊指令的使用如lgdt、lidt、cli等

(3)分页机制中PDE和PTE中的R/W和U/S等,提供了页级保护。

分页机制将线性地址与物理地址加以映射,提供了对物理地址的保护

特权级目的:

在于保护高特权的段,其中操作系统的内核处于最高的特权级

特权级意义:

在于保护模式中的特权级,对操作系统的“主奴机制”影响深远

7.在setup程序里曾经设置过gdt,为什么在head程序中将其废弃,又重新设置了一个?

为什么设置两次,而不是一次搞好?

原来的GDT位于setup中,将来此段内存会被缓冲区覆盖,所以必须将GDT设置head.s所在位置。

如果先将GDT设置在head所在区域,然后移动system模块,则GDT会被覆盖,如果先移动system在复制GDT,则head.s对应的程序会被覆盖掉,必须重建GDT。

若先移动system至0x0000再将GDT复制到0x5cb8-0x64b8处,虽然可以实现,但由于setup.s与head.s连接时不在同一文件,setup无法直接获取head中的gdt的偏移量,需事先写入,这会使设计失去一般性,给程序编写带来很大不便。

8.进程0的task_struct在哪?

具体内容是什么?

进程0的task_struct是操作系统设计者事先写好的,位于内核数据区,存储在user_task中(因为在进程0未激活之前,使用的是boot阶段的user_task)

Staticuniontask_unioninit_task={INIT_TASK};

具体内容如下:

包含了进程0的进程状态,进程0的LDT、进程0的TSS等等。

其中ldt设置了代码段和堆栈段的基址和线长(640KB)。

而TSS则保存了各种寄存器的值,包括各个段选择符。

9.内核的线性地址空间是如何分页的?

画出从0x000000开始的7个页(包括页目录表、页表所在页)的挂接关系图,就是页目录表的前四个页目录项、第一个个页表的前7个页表项指向什么位置?

给出代码证据。

head.s在setup_paging开始创建分页机制。

将页目录表和4个页表放在物理内存的起始位置开始的5个页空间内容全部清零(每页4kb),然后设置页目录表的前4项,分别指向4个页表。

然后开始从高地址向低地址方向填写4个页表,依次指向内存从高地址向低地址方向的各个页面。

即将第4个页表的最后一项(pg3+4092指向的位置)指向寻址范围的最后一个页面。

即从0Xfff000开始的4kb大小的内存空间。

将第4个页表的倒数第二个页表项(pg3-4+4092)指向倒数第二个页面,即0Xfff000-0x1000开始的4KB字节的内存空间

Head.s中:

Setup_paging:

Movl$1024*5,%ecx

Xorl%eax,%eax

Xorl%edi,%eax

Xorl%edi,%edi

Cld;rep;stosl

Movl$pg0+7pg

Movl

10.在head程序执行结束的时候,在idt的前面有184个字节的head程序的剩余代码,剩余了什么?

为什么要剩余?

11.为什么不用call,而是用ret“调用”main函数?

画出调用路线图,给出代码证据。

12.用文字和图说明中断描述符表是如何初始化的,可以举例说明(比如:

set_trap_gate(0,÷_error)),并给出代码证据。

13.在IA-32中,有大约20多个指令是只能在0特权级下使用,其他的指令,比如cli,并没有这个约定。

奇怪的是,在Linux0.11中,3特权级的进程代码并不能使用cli指令,这是为什么?

请解释并给出代码证据。

14.进程0的task_struct在哪?

具体内容是什么?

给出代码证据。

进程0的task_struct位于内核数据区,即task结构的第0项init_task。

Structtask_struct*task[NR_TASKS]={&(init_task,task)};

具体内容:

包含了进程0的进程状态、进程0的LDT、进程0的TSS等等。

其中ldt设置了代码段和堆栈段的基址和限长(640KB),而TSS则保存了各种寄存器的值,包括了各个段选择符。

具体值如下(课本P68)

15.在system.h里

#define_set_gate(gate_addr,type,dpl,addr)\

__asm__("movw%%dx,%%ax\n\t"\

"movw%0,%%dx\n\t"\

"movl%%eax,%1\n\t"\

"movl%%edx,%2"\

:

\

:

"i"((short)(0x8000+(dpl<<13)+(type<<8))),\

"o"(*((char*)(gate_addr))),\

"o"(*(4+(char*)(gate_addr))),\

"d"((char*)(addr)),"a"(0x00080000))

#defineset_intr_gate(n,addr)\

_set_gate(&idt[n],14,0,addr)

#defineset_trap_gate(n,addr)\

_set_gate(&idt[n],15,0,addr)

#defineset_system_gate(n,addr)\

_set_gate(&idt[n],15,3,addr)

这里中断门、陷阱门、系统调用都是通过_set_gate设置的,用的是同一个嵌入汇编代码,比较明显的差别是dpl一个是3,另外两个是0,这是为什么?

说明理由。

P61

Dpl表示的是特权级,0和3分别表示0特权级和3特权级。

异常处理是由内核来完成,Linux处于对内核的保护,不允许用户进程直接访问内核。

但是有些情况下,用户进程又需要内核代码的支持,因此就需要系统调用,它是用户进程与内核打交道的接口,是由用户进程直接调用的。

因此其在3特权级下

16.进程0fork进程1之前,为什么先调用move_to_user_mode()?

用的是什么方法?

解释其中的道理。

因为在Linux-011中,除进程0之外,所有进程都是由一个已有进程在用户态下完成创建的,但是此时进程0还处于内核态,因此要调用move_to_user_mode()函数,模仿终端返回的方式,实现进程0的特权级从内核态转化成用户态,又因为在Linux-0.11中转换特权级时采用中断和中断返回的方式,调用系统中断实现从3到0的特权级转换,中断返回时转换为3特权级。

因此,进程0从0特权级到3特权级转换时采用的是模拟中断返回

17.在Linux操作系统中大量使用了中断、异常类的处理,究竟有什么好处?

CPU是主机关键的组成部分,进程在主机中的运算肯定离不开CPU,而CPU在参与运算过程中免不了进行“异常处理”,这些异常处理都需要具体的服务程序来执行。

这种32位中断服务体系是为适应一种被动响应中断信号而建立的。

这样CPU就可以把全部精力都放在用户程序服务上,对于随时可能产生而又不可能时时都产生的中断信号,不用刻意去考虑,这就提高了操作系统的综合效率。

以“被动模型”代替“主动轮询”模式来处理中断问题是现代操作系统被称为“现代”一个标志。

18.copy_process函数的参数最后五项是:

longeip,longcs,longeflags,longesp,longss。

查看栈结构确实有这五个参数,奇怪的是其他参数的压栈代码都能找得到,确找不到这五个参数的压栈代码,反汇编代码中也查不到,请解释原因。

Copy_process执行时因为进程调用了fork函数,会导致中断,中断使CPU硬件自动将SS、ESP、EFLAGS、CS、EIP这几个寄存器的值按照顺序压入进程0内核栈,又因为函数传递参数是使用栈的,所以刚好可以作为copy_process的最后五项参数

19.分析get_free_page()函数的代码,叙述在主内存中获取一个空闲页的技术路线。

通过你想扫描页表位图mem_map,并由第一空页的下标左移12位家加LOW_MEM得到该页的物理地址,位于16M内存末端,代码如下(get_free_page)

Unsignedlong

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1