首页 > 其他分享 >操作系统高级教程期末思考题

操作系统高级教程期末思考题

时间:2023-02-20 10:11:38浏览次数:35  
标签:教程 操作系统 思考题 缓冲 代码 地址 内核 进程 函数

19年期末复习题

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

最开始启动计算机的时候,计算机内存未初始化,没有任何程序。而因为CPU只能读取内存中的程序,所以必须将操作系统先加载进内存当中才能使用操作系统的代码,这就需要使用BIOS。BIOS程序的入口地址为0xFFFF0,即为CS:IP指向位置,所以CPU就可以运行BIOS程序。

BIOS 需要完成一些检测工作,设置实模式下的中断向量表和服务程序,并将操作系统的引导扇区加载至 0x7C00 处,然后将跳转至 0x7C00运行操作系统自身的代码。所以计算机启动最开始运行的是BIOS代码。

2.为什么BIOS只加载了一个扇区,后续扇区却是由bootsect代码加载?为什么BIOS没有直接把所有需要加载的扇区都加载?

BIOS和操作系统的开发通常是不同的团队,按固定的规则约定,可以进行灵活的各自设计相应的部分。BIOS接到启动操作系统命令后,只从启动扇区将代码加载至0x7c00(BOOTSEG)位置,而后续扇区由bootsect代码加载。

bootsect代码由编写系统的用户负责,与之前BIOS无关。这样构建的好处是站在整个体系的高度,统一设计和统一安排,简单而有效。

如果要使用BIOS进行加载,而且加载完成之后再执行,则需要很长的时间,因此Linux采用的是边执行边加载的方法。

3.为什么BIOS把bootsect加载到0x07c00,而不是0x00000?加载后又马上挪到0x90000处,是何道理?为什么不一次加载到位?

加载0x07c00是BIOS提前约定设置的,不能加载到0x00000是因为从0x00000开始到0x003ff这1KB内存空间都是BIOS首先约定进行加载中断向量表的地方,不能进行覆盖。

而后挪到0x90000处是操作系统开始根据自己的需要安排内存了,具体原因如下:

① 内核会使用启动扇区中的一些数据,如第 508、509 字节处的 ROOT_DEV;

② 依据系统对内存的规划,内核占用 0x00000 开始的空间,因此 0x07c00 可能会被覆盖。

4.bootsect、setup、head程序之间是怎么衔接的?给出代码证据。

① bootsect跳转到setup程序:jmpi 0,SETUPSEG;

bootsect首先利用int 0x13中断分别加载setup程序及system模块,待bootsect程序的任务完成之后,执行代码jmpi 0,SETUPSEG。由于 bootsect 将 setup 段加载到了 SETUPSEG:0 (0x90200)的地方,在实模式下,CS:IP指向setup程序的第一条指令,此时setup开始执行。

② setup跳转到head程序:jmpi 0,8

执行setup后,内核被移到了0x00000处,CPU变为保护模式,执行jmpi 0,8

并加载了中断描述符表和全局描述符表。该指令执行后跳转到以GDT第2项中的 base_addr 为基地址,以0为偏移量的位置,其中base_addr为0。由于head放置在内核的头部,因此程序跳转到head中执行。

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

此时为32位保护模式,“0”表示段内偏移,“8”表示段选择符。转化为二进制:1000

最后两位00表示内核特权级,第三位0表示 GDT 表,第四位1表示根据GDT中的第2项来确定代码段的段基址和段限长等信息。可以得到代码是从head 的开始位置,段基址 0x00000000、偏移为 0 处开始执行的。

6.保护模式在“保护”什么?它的“保护”体现在哪里?特权级的目的和意义是什么?分页有“保护”作用吗?p438-440

(1) 保护模式在“保护”什么?它的“保护”体现在哪里?

保护操作系统的安全,不受到恶意攻击。保护进程地址空间。

“保护”体现在

打开保护模式后,CPU 的寻址模式发生了变化,基于 GDT 去获取代码或数据段的基址,相当于增加了一个段位寄存器。防止了对代码或数据段的覆盖以及代码段自身的访问超限。对描述符所描述的对象进行保护:在 GDT、 LDT 及 IDT 中,均有对应界限、特权级等;在不同特权级间访问时,系统会对 CPL、 RPL、 DPL、 IOPL 等进行检验,同时限制某些特殊指令如 lgdt, lidt,cli 等的使用;分页机制中 PDE 和 PTE 中的 R/W 和 U/S 等提供了页级保护,分页机制通过将线性地址与物理地址的映射,提供了对物理地址的保护。

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

特权级机制目的是为了进行合理的管理资源,保护高特权级的段。

意义是进行了对系统的保护,对操作系统的“主奴机制”影响深远。Intel 从硬件上禁止低特权级代码段使用部分关键性指令,通过特权级的设置禁止用户进程使用 cli、 sti 等指令。将内核设计成最高特权级,用户进程成为最低特权级。这样,操作系统可以访问 GDT、 LDT、 TR,而 GDT、 LDT 是逻辑地址形成线性地址的关键,因此操作系统可以掌控线性地址。物理地址是由内核将线性地址转换而成的,所以操作系统可以访问任何物理地址。而用户进程只能使用逻辑地址。总之,特权级的引入对操作系统内核进行保护。

(3)分页有“保护”作用吗?

分页机制有保护作用,使得用户进程不能直接访问内核地址,进程间也不能相互访问。用户进程只能使用逻辑地址,而逻辑地址通过内核转化为线性地址,根据内核提供的专门为进程设计的分页方案,由MMU非直接映射转化为实际物理地址形成保护。此外,通过分页机制,每个进程都有自己的专属页表,有利于更安全、高效的使用内存,保护每个进程的地址空间。

为什么特权级是基于段的?(超纲备用)

通过段,系统划分了内核代码段、内核数据段、用户代码段和用户数据段等不同的数据段,有些段是系统专享的,有些是和用户程序共享的,因此就有特权级的概念。

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

P33点评

8.进程0的task_struct在哪?具体内容是什么?

进程0的task_struct位于内核数据区,因为在进程0未激活之前,使用的是boot阶段的user_stack,因此存储在user_stack中。

具体内容如下:

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

代码如下:(若未要求没时间可不写)

INIT_TASK的定义见P68。

9.内核的线性地址空间是如何分页的?画出从0x000000开始的7个页(包括页目录表、页表所在页)的挂接关系图,就是页目录表的前四个页目录项、第一个个页表的前7个页表项指向什么位置?给出代码证据。

如何分页

head.s在setup_paging开始创建分页机制。将页目录表和4个页表放到物理内存的起始位置,从内存起始位置开始的5个页空间内容全部清零(每页4KB),然后设置页目录表的前4项,使之分别指向4个页表。然后开始从高地址向低地址方向填写4个页表,依次指向内存从高地址向低地址方向的各个页面。即将第4个页表的最后一项指向寻址范围的最后一个页面。即从0xFFF000开始的4kb 大小的内存空间。将第4个页表的倒数第二个页表项指向倒数第二个页面,即0xFFF000-0x1000开始的4KB字节的内存空间,依此类推。

挂接关系图

代码证据

P39最下面

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

剩余代码:

包含代码段如下after_page_tables(栈中压入了些参数)、 ignore_int(初始化中断时的中断处理函数) 和 setup_paging(初始化分页)。

剩余的原因:

after_page_tables 中压入的参数,为内核进入 main 函数的跳转做准备。设计者在栈中压入了 L6: main,以使得系统出错时,返回到 L6 处执行。

ignore_int 为中断处理函数,使用 ignore_int 将 idt 全部初始化,如果中断开启后存在使用了未设置的中断向量,那么将默认跳转到 ignore_int 处执行,使得系统不会跳转到随机的地方执行错误的代码。

setup_paging 进行初始化分页,在该函数中对 0x0000 和 0x5000 的进行了初始化操作。该代码用于跳转到 main,即执行“ret”指令。

11.为什么不用call,而是用ret“调用”main函数?画出调用路线图,给出代码证据。

CALL 指令会将 EIP 的值自动压栈,保护返回现场,然后执行被调函数,当执行到被调函数的ret指令时,自动出栈给 EIP .并还原现场,继续执行CALL 的下一行指令。在由head程序向main函数跳转时,不需main函数返回;且因为main函数是最底层的函数,无更底层的函数进行返回。因此要达到既调用 main又不需返回,选择ret。

调用路线图:见P42 图1-46。仿call示意图 下面部分

代码证据:

12.用文字和图说明中断描述符表是如何初始化的,可以举例说明(比如:set_trap_gate(0,&divide_error)),并给出代码证据。

(先画图见P54 图2-9然后解释)以set_trap_gate(0,÷_error)为例,其中,n是0,gate_addr是&idt[0],也就是idt的第一项中断描述符的地址;type是15,dpl(描述符特权级)是0;addr是中断服务程序divide_error(void)的入口地址。

代码证据:P53 代码

13.在IA-32中,有大约20多个指令是只能在0特权级下使用,其他的指令,比如cli,并没有这个约定。奇怪的是,在Linux0.11中,3特权级的进程代码并不能使用cli指令,这是为什么?请解释并给出代码证据。

根据Intel Manual,cli和sti指令与CPL和EFLAGS[IOPL]有关。通过IOPL来加以保护指令in,ins,out,outs,cli,sti等I/O敏感指令,只有CPL(当前特权级)<=IOPL才能执行,低特权级访问这些指令将会产生一个一般性保护异常。

IOPL位于EFLAGS的12-13位,仅可通过iret来改变,INIT_TASK中IOPL为0,在move_to_user_mode中直接执行“pushfl \n\t”指令,继承了内核的EFLAGS。IOPL的指令仍然为0没有改变,所以用户进程无法调用cli指令。因此,通过设置 IOPL, 3特权级的进程代码不能使用 cli 等I/O敏感指令。

具体代码:move_to_user_mode()此处一共两部分代码第一部分 P79

#define move_to_user_mode() \

asm(“movl %%esp, %%eax\n\t” \

​ ……

​ “pushfl\n\t” \ // ELAGS 进栈

​ ……

”)

第二部分代码见P 68 INIT_TASK

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))
#define set_intr_gate(n,addr) \
         _set_gate(&idt[n],14,0,addr)
 
#define set_trap_gate(n,addr) \
         _set_gate(&idt[n],15,0,addr)
#define set_system_gate(n,addr) \
         _set_gate(&idt[n],15,3,addr)

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

答:

当用户程序产生系统调用软中断后, 系统都通过system_call总入口找到具体的系统调用函数。 set_system_gate设置系统调用,须将 DPL设置为 3,允许在用户特权级(3)的进程调用,否则会引发 General Protection 异常。set_trap_gate 及 set_intr_gate 设置陷阱和中断为内核使用,需禁止用户进程调用,所以 DPL为 0。

16.进程0 fork进程1之前,为什么先调用move_to_user_mode()?用的是什么方法?解释其中的道理。

Linux操作系统规定,除进程 0 之外, 所有进程都是由一个已有进程在用户态下完成创建的。需要将进程0通过调用move_to_user_mode()从内核态转换为用户态。进程0从0特权级到3特权级转换时采用的是模仿中断返回。

设计者通过代码模拟 int(中断) 压栈, 当执行 iret 指令时, CPU 将SS,ESP,EFLAGS,CS,EIP 5 个寄存器的值按序恢复给 CPU, CPU之后翻转到 3 特权级去执行代码。

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

采用以“被动模式” 代替“主动轮询” 模式来处理终端问题。进程在主机中运算需用到 CPU,其中可能进行“异常处理” ,此时需要具体的服务程序来执行。 这种中断服务体系的建立是为了被动响应中断信号。因此, CPU 就可以更高效的处理用户程序服务, 不用考虑随机可能产生的中断信号,从而提高了操作系统的综合效率。

18.copy_process函数的参数最后五项是:long eip,long cs,long eflags,long esp,long ss。查看栈结构确实有这五个参数,奇怪的是其他参数的压栈代码都能找得到,确找不到这五个参数的压栈代码,反汇编代码中也查不到,请解释原因。

在 fork()中, 当执行“int $0x80” 时产生一个软中断, 使 CPU 硬件自动将 SS、 ESP、EFLAGS、 CS、 EIP 这 5 个寄存器的数值按这个顺序压入进程 0 的内核栈。 硬件压栈可确保 eip 的值指向正确的指令, 使中断返回后程序能继续执行。因为通过栈进行函数传递参数,所以恰可做为 copy_process 的最后五项参数。

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

通过逆向扫描页表位图 mem_map, 并由第一空页的下标左移 12 位加 LOW_MEM 得到该页的物理地址, 位于 16M 内存末端。P89代码考试不用看

过程:

① 将EAX 设置为0,EDI 设置指向mem_map 的最后一项(mem_map+PAGING_PAGES-1),std设置扫描是从高地址向低地址。从mem_map的最后一项反向扫描,找出引用次数为0(AL)的页,如果没有则退出;如果找到,则将找到的页设引用数为1;

② ECX左移12位得到页的相对地址,加LOW_MEM得到物理地址,将此页最后一个字节的地址赋值给EDI(LOW_MEM+4092);

③ stosl将EAX的值设置到ES:EDI所指内存,即反向清零1024*32bit,将此页清空;

④ 将页的地址(存放在EAX)返回。

20.分析copy_page_tables()函数的代码,叙述父进程如何为子进程复制页表。

P97一段话解释

21.进程0创建进程1时,为进程1建立了task_struct及内核栈,第一个页表,分别位于物理内存16MB顶端倒数第一页、第二页。请问,这两个页究竟占用的是谁的线性地址空间,内核、进程0、进程1、还是没有占用任何线性地址空间?说明理由(可以图示)并给出代码证据。

答:均占用内核的线性地址空间, 原因如下:

通过逆向扫描页表位图,并由第一空页的下标左移 12 位加 LOW_MEM 得到该页的物理地址,位于 16M 内存末端。 代码如下

unsigned long get_free_page(void)
{register unsigned long __res asm("ax");
__asm__("std ; repne ; scasb\n\t"
"jne 1f\n\t"
"movb $1,1(%%edi)\n\t"
"sall $12,%%ecx\n\t"
"addl %2,%%ecx\n\t"
"movl %%ecx,%%edx\n\t"
"movl $1024,%%ecx\n\t"
"leal 4092(%%edx),%%edi\n\t"
"rep ; stosl\n\t"
" movl %%edx,%%eax\n"
"1: cld"
:"=a" (__res)
:"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
"D" (mem_map+PAGING_PAGES-1)
);
return __res;
}

进程 0 和进程 1 的 LDT 的 LIMIT 属性将进程 0 和进程 1 的地址空间限定0~640KB, 所以进程 0、 进程 1 均无法访问到这两个页面, 故两页面占用内核的线性地址空间。进程 0 的局部描述符如下

include/linux/sched.h: INIT_TASK
/* ldt */ {0x9f,0xc0fa00}, \
{0x9f,0xc0f200}, \

内核线性地址等于物理地址(0x00000~0xfffff), 挂接操作的代码如下(head.s/setup_paging):

movl $pg0+7,pg_dir /* set present bit/user r/w */
movl $pg1+7,pg_dir+4 /* --------- " " --------- */
movl $pg2+7,pg_dir+8 /* --------- " " --------- */
movl $pg3+7,pg_dir+12 /* --------- " " --------- */
movl $pg3+4092,%edi
movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */
std
1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax
jge 1b

22.假设:经过一段时间的运行,操作系统中已经有5个进程在运行,且内核分别为进程4、进程5分别创建了第一个页表,这两个页表在谁的线性地址空间?用图表示这两个页表在线性地址空间和物理地址空间的映射关系。

内核的线性地址空间

注:65 和 81 应该改成 64 和 80

23.

#define switch_to(n) {\
struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,_current\n\t" \
         "je 1f\n\t" \
         "movw %%dx,%1\n\t" \
         "xchgl %%ecx,_current\n\t" \
         "ljmp %0\n\t" \
         "cmpl %%ecx,_last_task_used_math\n\t" \
         "jne 1f\n\t" \
         "clts\n" \
         "1:" \
         ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
         "d" (_TSS(n)),"c" ((long) task[n])); \
}

代码中的"ljmp %0\n\t" 很奇怪,按理说jmp指令跳转到得位置应该是一条指令的地址,可是这行代码却跳到了"m" (*&__tmp.a),这明明是一个数据的地址,更奇怪的,这行代码竟然能正确执行。请论述其中的道理。

答:其中a对应EIP,b对应CS,ljmp此时通过CPU中的电路进行硬件切换,进程由当前进程切换到进程n。CPU将当前寄存器的值保存到当前进程的TSS中,将进程n的TSS数据及LDT的代码段和数据段描述符恢复给CPU的各个寄存器,实现任务切换。

24.进程0开始创建进程1,调用fork(),跟踪代码时我们发现,fork代码执行了两次,第一次,执行fork代码后,跳过init()直接执行了for(;

标签:教程,操作系统,思考题,缓冲,代码,地址,内核,进程,函数
From: https://www.cnblogs.com/lolo9261/p/17136400.html

相关文章

  • 10. 操作系统和Linux
    进程和线程的区别线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同......
  • 【摄影】PS系列教程
    基础操作新建文档Ctrl+N分辨率常用像素每英寸颜色模式RGB:红绿蓝混合常用8bitCMRK图片大小修改图像大小Alt+Ctrl+I像素和分辨率的关系画面总像素......
  • 1 [初识]Vue3教程简介与Hello World编写 原创
    阅读目录​​前置知识​​​​下载VSCode​​​​编写第一个HelloWorld​​​​直接引入Vue3.x源码​​前置知识但是你还是需要会下面最基本的知识:1、HTML:超文本标记语......
  • ChatGPT详细教程,教你注册chatGPT,Openai的密钥怎么获取
       最近ChatPGT人工智能非常的火,我也体验了一把,感觉还是挺好玩的,这里分享一下,还有怎么拿到openai的密钥。1、打开注册页面:​​https://beta.openai.com/signup​​​......
  • 【GIT教程】一、GIT简易命令行入门教程
    一、创建仓库在注册完成并成功登录Gitee账号后,用户可以开始创建自己的第一个仓库。1、通过网站右上角的「+」号,选择「新建仓库」,进入新建仓库页面2、在新建仓库页面......
  • 利用Quartus 18.0设计Nios II系统教程
    最后修改日期:2023/02/191.概要1.1.软件Quartus18.0PrimeStandard及内部工具1.2.电路板AlteraDE2-115开发板1.3.PLD器件信号FPGA:AlteraCycloneIVENo:E......
  • 2023年软考网络规划设计师视频教程
    很多考生准备参加2023年软考网络规划设计师考试,为帮助考生顺利通过考试,课课家软考学院为考生推荐网络规划设计师学习视频、串讲视频、真题讲解视频等内容,帮助考生掌握......
  • SVM之Libsvm工具包的安装教程(转载)
    SVM之Libsvm工具包的安装教程https://blog.csdn.net/qq_43493562/article/details/110918276  ......
  • 操作系统学习笔记总纲
    操作系统学习笔记目录第1章计算机系统概述1.1操作系统的基本概念1.1.1操作系统的概念1.1.2操作系统的特征1.1.3操作系统的目标和功能1.2操作......
  • ASUS RAMCache 使用教程
    硬盘加速软件,华硕出品,该版本为解除限制版,任何电脑都可以使用。安装好ASUSRAMCache软件后,先不要重新启动,复制解除限制的补丁文件,打开安装目录,默认是C:\ProgramFiles(......