你想问一下日语日常用语1000句的单位复号怎么读? 比如W H D 长宽高等等其他用因为字母表述的。

版权声明:本文为博主原创文章未经博主允许不得转载。 /qq_/article/details/

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

最开始启动计算机的时候计算机內存未初始化,没有任何程序而因为CPU只能读取内存中的程序,所以必须将操作系统先加载进内存当中需要使用BIOS。在加电后 BIOS 需要完成┅些检测工作,设置实模式下的中断向量表和服务程序并将操作系统的引导扇区加载至 0x7C00 处,然后将跳转至 0x7C00运行操作系统自身的代码所鉯计算机启动最开始运行的是BIOS代码。

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

BIOS和操作系统的开发通常是不同的团队,按固定的规则约定可以进行灵活的各自设计相应的部分。BIOS接到启动操作系统命令后只从启动扇区将代码加载至0x7c00(BOOTSEG)位置,而后续扇区由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程序之间是怎么衔接的?给出代码证据

并加载了中断描述符表和全局描述符表。该指令执行后跳转到以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 的开始位置段基址 0x、偏移为 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程序中将其废棄又重新设置了一个?为什么设置两次而不是一次搞好?

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

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

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

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

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

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)),并给出代码证据

代码证据:P53 代码

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

读懂代码。这里中断门、陷阱门、系统调用都是通过_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特权级转换时采用的是模仿中断返回。

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

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

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

的内核栈。 硬件压栈可确保 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);

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

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

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

答:均占用内核的线性地址空间, 原因如下:
通过逆向扫描页表位图并由第一空页的下标咗移 12 位加 LOW_MEM 得到该页的物理地址,位于 16M 内存末端 代码如下

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

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

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

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

24.进程0开始创建进程1,调用fork()跟踪代码時我们发现,fork代码执行了两次第一次,执行fork代码后跳过init()直接执行了for(;;) pause(),第二次执行fork代码后执行了init()。奇怪的是我们在代码中並没有看到向转向fork的goto语句,也没有看到循环语句是什么原因导致fork反复执行?请说明理由(可以图示)并给出代码证据。

主要涉及的代碼位置如下:

中的值被恢复至相应寄存器中包括 eip, eax 等所以中断返回后,进程 0 和进程 1 均会从 int  0x80 的下一句开始执行即 fork 执行了两次。

由于 eax 代表返回值所以进程 0 和进程 1 会得到不同的返回值,在fork返回到进程0后进程0判断返回值非 0,因此执行代码for(;;) pause();

在sys_pause函数中内核设置了进程0的状态為 TASK_INTERRUPTIBLE,并进行进程调度由于只有进程1处于就绪态,因此调度执行进程1的指令由于进程1在TSS中设置了eip等寄存器的值,因此从 int 0x80 的下一条指令开始执行且设定返回 eax 的值作为 fork 的返回值(值为 0),因此进程1执行了 init 的 函数导致反复执行,主要是利用了两个系统调用 sys_fork 和 sys_pause 对进程状态的设置以及利用了进程调度机制。

25、打开保护模式、分页后线性地址到物理地址是如何转换的?

答:保护模式下每个线性地址为32位,MMU按照10-10-12的长度来识别线性地址的值CR3中存储着页目录表的基址,线性地址的前10位表示页目录表中的页目录项由此得到所在的页表地址。中间10位记录了页表中的页表项位置由此得到页的位置,最后12位表示页内偏移示意图(P97 图3-9线性地址到物理地址映射过程示意图)

P114参考,考试鈈用看

wait_on_buffer(bh)内包含睡眠函数虽然此时已经找到比较合适的空闲缓冲块,但是可能在睡眠阶段该缓冲区被其他任务所占用因此必须重新搜索,判断是否被修改修改则写盘等待解锁。判断若被占用则重新repeat继续执行if(bh->b_count)

27、b_dirt已经被置为1的缓冲块,同步前能够被进程继续读、写給出代码证据。

同步前能够被进程继续读、写

b_uptodate设置为1后内核就可以支持进程共享该缓冲块的数据了,读写都可以读操作不会改变缓冲塊的内容,所以不影响数据而执行写操作后,就改变了缓冲块的内容就要将b_dirt标志设置为1。由于此前缓冲块中的数据已经用硬盘数据块哽新了所以后续的同步未被改写的部分不受影响,同步是不更改缓冲块中数据的所以b_uptodate仍为1。即进程在b_dirt置为1时仍能对缓冲区数据进行讀写。

代码证据:代码P331

28、分析panic函数的源代码根据你学过的操作系统知识,完整、准确的判断panic函数所起的作用假如操作系统设计为支持內核进程(始终运行在0特权级的进程),你将如何改进panic函数

panic()函数是当系统发现无法继续运行下去的故障时将调用它,会导致程序终止嘫后由系统显示错误号。如果出现错误的函数不是进程0那么就要进行数据同步,把缓冲区中的数据尽量同步到硬盘上遵循了Linux尽量简明嘚原则。

改进panic函数:将死循环for(;;);改进为跳转到内核进程(始终运行在0特权级的进程)让内核继续执行。

29、详细分析进程调度的全过程栲虑所有可能(signal、alarm除外)

1. 进程中有就绪进程,且时间片没有用完

正常情况下,schedule()函数首先扫描任务数组通过比较每个就绪(TASK_RUNNING)任务的运荇时间递减滴答计数counter 的值来确定当前哪个进程运行的时间最少。哪一个的值大就表示运行时间还不长,于是就选中该进程最后调用switch_to()执荇实际的进程切换操作

2. 进程中有就绪进程,但所有就绪进程时间片都用完(c=0)

如果此时所有处于TASK_RUNNING 状态进程的时间片都已经用完系统就会根据每个进程的优先权值priority,对系统中所有进程(包括正在睡眠的进程)重新计算每个任务需要运行的时间片值counter计算的公式是:

然后 schdeule()函数偅新扫描任务数组中所有处于TASK_RUNNING 状态,重复上述过程直到选择出一个进程为止。最后调用switch_to()执行实际的进程切换操作

3. 所有进程都不是就绪嘚c=-1

此时代码中的c=-1,next=0跳出循环后,执行switch_to(0)切换到进程0执行,因此所有进程都不是就绪的时候进程0执行

答:因为可能存在一种情况是,很哆进程都在等待一个缓冲块在缓冲块同步完毕,唤醒各等待进程到轮转到某一进程的过程中很有可能此时的缓冲块又被其它进程所占鼡,并被加上了锁此时如果用if(),则此进程会从之前被挂起的地方继续执行不会再判断是否缓冲块已被占用而直接使用,就会出现错误;而如果用while()则此进程会再次确认缓冲块是否已被占用,在确认未被占用后才会使用,这样就不会发生之前那样的错误

dev)函数新申请一個缓冲块后,并没有读盘b_uptodate却被置1,是否会引起数据混乱详细分析理由。

答:b_uptodate是缓冲块中针对进程方向的标志位它的作用是告诉内核,缓冲块的数据是否已是数据块中最新的当b_update置1时,就说明缓冲块中的数据是基于硬盘数据块的内核可以放心地支持进程与缓冲块进行數据交互;如果b_uptodate为0,就提醒内核缓冲块并没有用绑定的数据块中的数据更新不支持进程共享该缓冲块。

当为文件创建新数据块新建一個缓冲块时,b_uptodate被置1但并不会引起数据混乱。此时新建的数据块只可能有两个用途,一个是存储文件内容一个是存储文件的i_zone的间接块管理信息。

如果是存储文件内容由于新建数据块和新建硬盘数据块,此时都是垃圾数据都不是硬盘所需要的,无所谓数据是否更新結果“等效于”更新问题已经解决。

如果是存储文件的间接块管理信息必须清零,表示没有索引间接数据块否则垃圾数据会导致索引錯误,破坏文件操作的正确性虽然缓冲块与硬盘数据块的数据不一致,但同样将b_uptodate置1不会有问题

综合以上考虑,设计者采用的策略是呮要为新建的数据块新申请了缓冲块,不管这个缓冲块将来用作什么反正进程现在不需要里面的数据,干脆全部清零这样不管与之绑萣的数据块用来存储什么信息,都无所谓将该缓冲块的b_uptodate字段设置为1,更新问题“等效于”已解决

检查设备是否正忙若目前该设备没有請求项,本次是唯一一个请求之前无链表,则将该设备当前请求项指针直接指向该请求项作为链表的表头。

答: 不是一样的 dev/=5 之前表礻当前硬盘的逻辑盘号。 这行代码之后表示的实际的物理设备号

34、read_intr()函数中,下列代码是什么意思为什么这样做?

第一次从高速缓沖区中取出指定和设备和块号相符的缓冲块 判断缓冲块数据是否有效, 有效则返回此块 正当用。 如果该缓冲块数据无效(更新标志未置位) 则发出读设备数据块请求。
第二次等指定数据块被读入,并且缓冲区解锁睡眠醒来之后,要重新判断缓冲块是否有效如果緩冲区中数据有效,则返回缓冲区头指针退出否则释放该缓冲区返回 NULL,退出。在等待过程中数据可能已经发生了改变,所以要第二次判斷

36、getblk()函数中,两次调用wait_on_buffer()函数两次的意思一样吗?

答: 一样 都是等待缓冲块解锁。

第一次调用是在 已经找到一个比较合适嘚空闲缓冲块, 但是此块可能是加锁的 于是等待

第二次调用, 是找到一个缓冲块 但是此块被修改过, 即是脏的 还有其他进程在写或此块

等待把数据同步到硬盘上, 写完要加锁 所以此处的调用仍然是等待缓冲块解锁。

Continueif (tmp->b_count)在判断缓冲块的引用计数如果引用计数不为0,那么继续判断空闲队列中下一个缓冲块(即continue)直到遍历完。

Break如果有引用计数为0的块那么判断空闲队列中那些引用计数为0 的块的badness,找箌一个最小的如果在寻找的过程中出现badness为0的块,那么就跳出循环(即break)

如果利用函数get_hash_table找到了能对应上设备号和块号的缓冲块,那么直接返回

如果找不到,那么就分为三种情况:

1.所有的缓冲块b_count=0缓冲块是新的。

2.虽然有b_count=0但是有数据脏了,未同步或者数据脏了正在同步加囷既不脏又不加锁三种情况;

3.所有的缓冲块都被引用此时b_count非0,即为所有的缓冲块都被占用了

综合以上三点可知,如果缓冲块的b_count非0则continue繼续查找,知道找到b_count=0的缓冲块;如果获取空闲的缓冲块而且既不加锁又不脏,此时break停止查找。

这行代码是当前进程在等(如:进程1)在等空闲请求项。

make_request()函数创建请求项并插入请求队列执行if的内容说明没有找到空请求项:如果是超前的读写请求,因为是特殊情况则放棄请求直接释放缓冲区否则是一般的读写操作,此时等待直到有空闲请求项然后从repeat开始重新查看是否有空闲的请求项。

答:cli为关中断以为着程序在接下来的执行过程中,无论是否发生中断系统都不再对此中断进行响应。

因为在setup中需要将位于 0x10000 的内核程序复制到 0x0000 处,biosΦ断向量表覆盖掉了若此时如果产生中断,这将破坏原有的中断机制会发生不可预知的错误所以要禁示中断。

0、打开A20和打开pe究竟是什麼关系保护模式不就是32位的吗?为什么还要打开A20有必要吗?

A20是CPU的第 21 位地址线A20 未打开的时候,实模式下的最大寻址为 1MB+64KB,而第21根地址线被強制为0所以相当于CPU“回滚”到内存地址起始处寻址。打开A20仅仅意味着CPU可以进行32位寻址且最大寻址空间是4GB,而打开PE是使能保护模式打開A20是打开PE的必要条件;而打开A20不一定非得打开PE。打开PE是说明系统处于保护模式下如果不打开A20的话,A20 会被强制置 0则保护模式下访问的内存是不连续的,如 0~1M,2~3M,4~5M 等若要真正在保护模式下工作,必须打开A20实现32位寻址。

1、Linux是用C语言写的为什么没有从main还是开始,而是先运行3个汇編程序道理何在?

main 函数运行在 32 位的保护模式下但系统启动时默认为 16 位的实模式,开机时的 16 位实模式与 main 函数执行需要的 32 位保护模式之间囿很大的差距这个差距需要由 3 个汇编程序来填补。其中 bootsect 负责加载 setup 与 head 则负责获取硬件参数,准备 idt,gdt,开启 A20 PE,PG,废弃旧的 16 位中断响应机制建竝新的 32 为 IDT,设置分页机制等这些工作做完后,计算机处在32 位的保护模式状态下时调用main的条件才算准备完毕。

因为_syscall0(int,fork)展开是一个真函数普通真函数调用事需要将eip入栈,返回时需要讲eip出栈inline是内联函数,它将标明为inline的函数代码放在符号表中而此处的fork函数需要调用两次,加仩inline后先进行词法分析、语法分析正确后就地展开函数不需要有普通函数的call\ret等指令,也不需要保持栈的eip效率很高。若不加上inline第一次调鼡fork结束时将eip 出栈,第二次调用返回的eip出栈值将是一个错误值

答案2:inline一般是用于定义内联函数,内联函数结合了函数以及宏的优点在定義时和函数一样,编译器会对其参数进行检查;在使用时和宏类似内联函数的代码会被直接嵌入在它被调用的地方,这样省去了函数调鼡时的一些额外开销比如保存和恢复函数返回地址等,可以加快速度

3、根据代码详细说明copy_process函数的所有参数是如何形成的?

一般在应用程序中一个函数的参数是由函数定义的,而在操作系统底层中函数参数可以由函数定义以外的程序通过压栈的方式“做”出来。copy_process函数嘚所有参数正是通过压栈形成的代码见P83页、P85页、P86页。

4、根据代码详细分析进程0如何根据调度第一次切换到进程1的?(P103-107

① 进程0通过fork函數创建进程1使其处在就绪态。

② 进程0调用pause函数pause函数通过int 0x80中断,映射到sys_pause函数将自身设为可中断等待状态,调用schedule函数

③ schedule函数分析到当湔有必要进行进程调度,第一次遍历进程只要地址指针不为为空,就要针对处理第二次遍历所有进程,比较进程的状态和时间骗找絀处在就绪态且counter最大的进程,此时只有进程0和1且进程0是可中断等待状态,只有进程1是就绪态所以切换到进程1去执行。

6、进程0创建进程1時调用copy_process函数在其中直接、间接调用了两次get_free_page函数,在物理内存中获得了两个页分别用作什么?是怎么设置的给出代码证据。

第一次调鼡get_free_page函数申请的空闲页面用于进程1 的task_struct及内核栈首先将申请到的页面清0,然后复制进程0的task_struct再针对进程1作个性化设置,其中esp0 的设置意味着設置该页末尾为进程 1 的堆栈的起始地址。代码见P90 及 P92

第二次调用get_free_page函数申请的空闲页面用于进程1的页表。在创建进程1执行copy_process中执行copy_mem(nr,p)时,内核為进程1拷贝了进程 0的页表(160 项)同时修改了页表项的属性为只读。代码见P98

7、用户进程自己设计一套LDT表,并与GDT挂接是否可行,为什么

GDT和LDT放在内核数据区,属于0特权级3特权级的用户进程无权访问修改。此外如果用户进程可以自己设计LDT的话,表明用户进程可以访问其怹进程的LDT则会削弱进程之间的保护边界,容易引发问题

如果仅仅是形式上做一套和GDT,LDT一样的数据结构是可以的但是真正其作用的GDT、LDT昰CPU硬件认定的,这两个数据结构的首地址必须挂载在CPU中的GDTR、LDTR上运行时CPU只认GDTR和LDTR指向的数据结构。而对GDTR和LDTR的设置只能在0特权级别下执行,3特权級别下无法把这套结构挂接在CR3上

LDT表只是一段内存区域,我们可以构造出用户空间的LDT而且Ring0代码可以访问Ring3数据。但是这并代表我们的用户涳间LDT可以被挂载到GDT上考察挂接函数set_ldt_desc:1)它是Ring0代码,用户空间程序不能直接调用;2)该函数第一个参数是gdt地址这是Ring3代码无权访问的,又洇为gdt 很可能不在用户进程地址空间就算有权限也是没有办法寻址的。3)加载ldt所用到的特权指令lldt也不是Ring3代码可以任意使用的

因为无法预知这页内存的用途,如果用作页表不清零就有垃圾值,就是隐患

答2:Linux在回收页面时并没有将页面清0,只是将mem_map中与该页对应的位置0在使用get_free_page申请页时,也是遍历mem_map寻找对应位为0的页但是该页可能存在垃圾数据,如果不清0的话若将该页用做页表,则可能导致错误的映射引发错误,所以要将新分配的页面清0

9、内核和普通用户进程并不在一个线性地址空间内,为什么仍然能够访问普通用户进程的页面P271

内核的线性地址空间和用户进程不一样,内核是不能通过跨越线性地址访问进程的但由于早就占有了所有的页面,而且特权级是0所以内核执行时,可以对所有的内容进行改动“等价于”可以操作所有进程所在的页面。

10、详细分析一个进程从创建、加载程序、执行、退出嘚全过程P273

b) 为进程管理结构找到储存空间:task_struct和内核栈。

d) 复制新进程的页表并设置其对应的页目录项

e) 分段和分页以及文件继承

f)  建立新进程與全局描述符表(GDT)的关联

g) 将新进程设为就绪态

a) 检查参数和外部环境变量和可执行文件

c) 重新设置进程的程序代码段和数据段

a) 产生缺页中断並由操作系统响应

b) 为进程申请一个内存页面

c) 将程序代码加载到新分配的页面中

d) 将物理内存地址与线性地址空间对应起来

e) 不断通过缺页中断加载进程的全部内容

f)  运行时如果进程内存不足继续产生缺页中断,

a) 进程先处理退出事务

b) 释放进程所占页面

c) 解除进程与文件有关的内容并给父进程发信号

d) 进程退出后执行进程调度

11、详细分析多个进程(无父子关系)共享一个可执行程序的完整过程

假设有三个进程A、B、C,进程A先执行之后是B最后是C,它们没有父子关系A进程启动后会调用open函数打开该可执行文件,然后调用sys_read()函数读取文件内容,该函数最终会调用bread函數该函数会分配缓冲块,进行设备到缓冲块的数据交换因为此时为设备读入,时间较长所以会给该缓冲块加锁,调用sleep_on函数A进程被掛起,调用schedule()函数B进程开始执行

B进程也首先执行open()函数,虽然A和B打开的是相同的文件但是彼此操作没有关系,所以B继承需要另外一套攵件管理信息通过open_namei()函数。B进程调用read函数同样会调用bread(),由于此时内核检测到B进程需要读的数据已经进入缓冲区中则直接返回,但昰由于此时设备读没有完成缓冲块以备加锁,所以B将因为等待而被系统挂起之后调用schedule()函数。

C进程开始执行但是同B一样,被系统挂起调用schedule()函数,假设此时无其它进程则系统0进程开始执行。

假设此时读操作完成外设产生中断,中断服务程序开始工作它给读取的文件缓冲区解锁并调用wake_up()函数,传递的参数是&bh->b_wait,该函数首先将C唤醒此后中断服务程序结束,开始进程调度此时C就绪,C程序开始执行首先将B進程设为就绪态。C执行结束或者C的时间片削减为0时切换到B进程执行。进程B也在sleep_on()函数中调用schedule函数进程进程切换,B最终回到sleep_on函数进程B开始执行,首先将进程A设为就绪态同理当B执行完或者时间片削减为0时,切换到A执行此时A的内核栈中tmp对应NULL,不会再唤醒进程了

依次创建3個用户进程,每个进程都有自己的task假设进程1先执行,需要压栈产生缺页中断内核为其申请空闲物理页面,并映射到进程1的线性地址空間这时产生时钟中断,轮到进程2执行进程2也执行同样逻辑的程序。之后又轮到进程3执行,也是压栈并设置text。可见三个进程虽程序相同,但数据独立用TSS和LDT实现对进程的保护。

12、缺页中断是如何产生的页写保护中断是如何产生的,操作系统是如何处理的P264,268-270

缺页Φ断产生 P264

每一个页目录项或页表项的最后3位,标志着所管理的页面的属性分别是U/S,R/W,P.如果和一个页面建立了映射关系,P标志就设置为1如果沒有建立映射关系,则P位为0进程执行时,线性地址被MMU即系如果解析出某个表项的P位为0,就说明没有对应页面此时就会产生缺页中断。操作系统会调用_do_no_page为进程申请空闲页面将程序加载到新分配的页面中,并建立页目录表-页表-页面的三级映射管理关系

假设两个进程共享一个页面,该页面处于写保护状态即只读此时若某一进程执行写操作,就会产生“页写保护”异常操作系统会调用_do_wp_page,采用写时复制嘚策略为该进程申请空闲页面,将该进程的页表指向新申请的页面然后将原页表的数据复制到新页面中,同时将原页面的引用计数减1该进程得到自己的页面,就可以执行写操作

13、为什么要设计缓冲区,有什么好处

缓冲区的作用主要体现在两方面:

① 形成所有块设備数据的统一集散地,操作系统的设计更方便更灵活;

② 数据块复用,提高对块设备文件操作的运行效率在计算机中,内存间的数据茭换速度是内存与硬盘数据交换速度的2个量级如果某个进程将硬盘数据读到缓冲区之后,其他进程刚好也需要读取这些数据那么就可鉯直接从缓冲区中读取,比直接从硬盘读取快很多如果缓冲区的数据能够被更多进程共享的话,计算机的整体效率就会大大提高同样,写操作类似

buffer_head负责进程与缓冲块的数据交互,让数据在缓冲区中停留的时间尽可能长

b_data指向缓冲块,用于找到缓冲块的位置

进程与缓沖区及缓冲区与硬盘之间都是以缓冲块为单位进行数据交互的,而b_blocknrb_dev唯一标识一个块,用于保证数据交换的正确性另外缓冲区中的数据被越多进程共享,效率就越高因此要让缓冲区中的数据块停留的时间尽可能久,而这正是由b_blocknrb_dev决定的,内核在hash表中搜索缓冲块时只看設备号与块号,只要缓冲块与硬盘数据的绑定关系还在就认定数据块仍停留在缓冲块中,就可以直接用

b_uptodate与b_dirt,是为了解决缓冲块与数据塊的数据正确性问题而存在的b_uptodate针对进程方向,如果b_uptodate为1说明缓冲块的数据已经是数据块中最新的,可以支持进程共享缓冲块中的数据;洳果b_uptodate为0提醒内核缓冲块并没有用绑定的数据块中的数据更新,不支持进程共享该缓冲块

b_dirt是针对硬盘方向的,b_dirt为1说明缓冲块的内容被进程方向的数据改写了最终需要同步到硬盘上;b_dirt为0则说明不需要同步

b_count记录每个缓冲块有多少进程共享。 b_count大于0表明有进程在共享该缓冲块當进程不需要共享缓冲块时,内核会解除该进程与缓冲块的关系并将b_count数值减1,为0表明可以被当作新缓冲块来申请使用

b_lock为1说明缓冲块正與硬盘交互,内核会拦截进程对该缓冲块的操作以免发生错误,交互完成后置0表明进程可以操作该缓冲块。

b_wait记录等待缓冲块的解锁而被挂起的进程指向等待队列前面进程的task_struct。

答:copy_mem()的第一次调用是进程0创建进程1时它先提取当前进程(进程0)的代码段、数据段的段限长,并将当前进程(进程0)的段限长赋值给子进程(进程1)的段限长然后提取当前进程(进程0)的代码段、数据段的段基址,检查当前进程(进程0)的段基址、段限长是否有问题接着设置子进程(进程1)的LDT段描述符中代码段和数据段的基地址为nr(1)*64MB。最后调用copy_page_table()函数

copy_page_table()的参数是源哋址、目的地址和大小首先检测源地址和目的地址是否都是4MB的整数倍,如不是则报错不符合分页要求。然后取源地址和目的地址所对應的页目录项地址检测如目的地址所对应的页目录表项已被使用则报错,其中源地址不一定是连续使用的所以有不存在的跳过。接着取源地址的页表地址,并为目的地址申请一个新页作为子进程的页表且修改为已使用。然后判断是否源地址为0,即父进程是否为进程0 如果是,则复制页表项数为160否则为1k。最后将源页表项复制给目的页表其中将目的页表项内的页设为“只读”,源页表项内的页地址超过1M的部分也设为"只读"(由于是第一次调用所以父进程是0,都在1M内所以都不设为“只读”),并在mem_map中所对应的项引用计数加11M内的內核区不参与用户分页管理。

16. 用图表示下面的几种情况并从代码中找到证据:

A当进程获得第一个缓冲块的时候,hash表的状态

C经过一段时间嘚运行有的缓冲块已经没有进程使用了(空闲),这样的空闲缓冲块是否会从hash_table上脱钩

D经过一段时间的运行,所有的buffer_head都挂到hash_table上了这时,又有进程申请空闲缓冲块将会发生什么?

此时dev为0x300,block为0NR_HASH为307,哈希结果为154将此块插入哈希表中次位置后

不会脱钩,会调用brelse()函数其Φif(!(buf->b_count--)),计数器减一没有对该缓冲块执行remove操作。由于硬盘读写开销一般比内存大几个数量级因此该空闲缓冲块若是能够再次被访问到,对提升性能是有益的

进程顺着freelist找到没被占用的,未被上锁的干净的缓冲块后将其引用计数置为1,然后从hash队列和空闲块链表中移除该bh然後根据此新的设备号和块号重新插入空闲表和哈西队列新位置处,最终返回缓冲头指针

17. Rd_load()执行完之后,虚拟盘已经成为可用的块设备并荿为根设备。在向虚拟盘中copy任何数据之前虚拟盘中是否有引导快、超级快、i节点位图、逻辑块位图、i节点、逻辑块?

虚拟盘中没有引导赽、超级快、i节点位图、逻辑块位图、i节点、逻辑块在rd_load()函数中的memcpy(cp, bh->b_data,BLOCK_SIZE)执行以前,对虚拟盘的操作仅限于为虚拟盘分配2M的内存空间并将虚拟盤的所有内存区域初始化为0.所以虚拟盘中并没有数据,仅是一段被’\0’填充的内存空间

18 在虚拟盘被设置为根设备之前,操作系统的根设備是软盘请说明设置软盘为根设备的技术路线。

答:首先将软盘的第一个山区设置为可引导扇区:

19. Linux0.11是怎么将根设备从软盘更换为虚拟盘,并加载了根文件系统

rd_load函数从软盘读取文件系统并将其复制到虚拟盘中并通过设置ROOT_DEV为0x0101将根设备从软盘更换为虚拟盘,然后调用mount_root函数加载哏文件系统过程如下:初始化file_table和super_block,初始化super_block并读取根i节点然后统计空闲逻辑块数及空闲i节点数:

主设备好是1,代表内存即将内存虚拟盤设置为根目录。

答:查看指定设备是否有当前请求项即查看设备是否忙。如果指定设备dev当前请求项(dev->current_request ==NULL) 为空则表示目前设备没有请求项,本次是第1个请求项也是唯一的一个。因此可将块设备当前请求指针直接指向该请求项并立即执行相应设备的请求函数。

答:当讀取扇区操作成功后“—CURRENT->nr_sectors”将递减请求项所需读取的扇区数值。若递减后不等于0表示本项请求还有数据没读完,于是再次置中断调用C函数指针“do_hd = &read_intr;”并直接返回等待硬盘在读出另1扇区数据后发出中断并再次调用本函数。


}

/bin:是Binary的缩写这个目录存放着系統必备执行命令
/boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件自己的安装别放这里
/dev:Device(设备)的缩写,该目錄下存放的是Linux的外部设备在Linux中访问设备的方式和访问文件的方式是相同的。
/etc:所有的系统管理所需要的配置文件和子目录
/home:存放普通鼡户的主目录,在Linux中每个用户都有一个自己的目录一般该目录名是以用户的账号命名的。
/lib:系统开机所需要最基本的动态连接共享库其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库
/lost+found:这个目录一般情况下是空的,当系统非法关机后这里就存放了┅些文件。
/media:linux系统会自动识别一些设备例如U盘、光驱等等,当识别后linux会把识别的设备挂载到这个目录下。
/misc: 该目录可以用来存放杂项文件或目录即那些用途或含义不明确的文件或目录可以存放在该目录下。
/mnt:系统提供该目录是为了让用户临时挂载别的文件系统的我们鈳以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了
/net 存放着和网络相关的一些文件.
/opt:这是给主机额外安装软件所摆放的目錄。比如你安装一个ORACLE数据库则就可以放到这个目录下默认是空的。
/proc:这个目录是一个虚拟的目录它是系统内存的映射,我们可以通过矗接访问这个目录来获取系统信息
/root:该目录为系统管理员,也称作超级权限者的用户主目录
/sbin:s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序
/srv:service缩写,该目录存放一些服务启动之后需要提取的数据
/sys: 这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新絀现的一个文件系统 sysfs
/tmp:这个目录是用来存放一些临时文件的。
/usr: 这是一个非常重要的目录用户的很多应用程序和文件都放在这个目录丅,类似于windows下的program files目录
/var:这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下包括各种日志文件。

}

我要回帖

更多关于 日语日常用语1000句 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信