Musel's blog

BUAA-OS-Lab3

字数统计: 2k阅读时长: 7 min
2022/04/26

操作系统 Lab3:进程与调度

一、实验思考题

Thinking 3.1

思考 envid2env 函数: 为什么 envid2env 中需要判断 e->env_id !=envid 的情况?如果没有这步判断会发生什么情况?

  • mkenvid(struct Env *e)中生成的envid为(asid << (1 + LOG2NENV)) | (1 << LOG2NENV) | idx,即asid|有效位|env结构体在envs数组的偏移
  • envid2env(u_int envid, struct Env **penv, int checkperm)中通过envid的偏移找到结构体e=envs+ENVX(envid);。而此时不能确保所给envid中asid的有效性。所以需要通过再次判断e->env_id !=envid保证进程块的asid.
  • 若此index所对的env已经更换,则新env结构体会对应新的ASID。如果没有这步判断,可能会出现:①所给envid所对的结构体已经被free后再次使用,即旧结构体所代表的PCB被淘汰,而此时得到的新env与envid想找的旧结构体不匹配;②env结构体没有成功切换为新进程的PCB,导致asid匹配出现错误。

Thinking 3.2 结合 include/mmu.h 中的地址空间布局,思考 env_setup_vm 函数:

UTOP 和 ULIM 的含义分别是什么?

  • ULIM: user limit:kuseg用户态上限,0x8000 0000区分内核态和用户态的地址
  • UTOP: userSpace top:用户可分配虚拟内存上限

UTOP 和 ULIM 之间的区域与 UTOP 以下的区域相比有什么区别?

  • UTOP 和 ULIM 之间的区域:
    • 用与存放页表和内核结构体,用户不可自由分配,即env中结构体数组的pgdir被清零后不会被赋值
    • 其中UPAGES和ENVS其所占的物理页面,除了映射到用户态的这一部分虚拟地址,还与内核中的虚拟地址有一一映射关系。
  • UTOP 以下的区域:占用物理内存,但是以页表形式,没有物理内存和内核地址的一一映射

请结合系统自映射机制解释 Step4 中pgdir[PDX(UVPT)]=env_cr3的含义。

  • 内核态中的虚拟页目录的第PDX(UVPT)个页目录项中保存着此页目录所在页表的基地址的物理地址env_cr3

谈谈自己对进程中物理地址和虚拟地址的理解。

  • 每个进程都有kuseg的2G虚拟空间,但是实际所有进程共享相同的内存空间。不同的进程有相同的虚拟地址,但是相同虚拟地址映射到不同物理地址

Thinking 3.3

找到 user_data 这一参数的来源,思考它的作用。没有这个参数可不可以?为什么?(可以尝试说明实际的应用场景,举一个实际的库中的例子)

  • 来源:env_create_priority()函数中alloc的Env结构体指针
  • 这个参数的作用是传给load_elf函数,并作为load_elf的int* map函数的参数,获得结构体的页目录
  • c语言库函数中qsort()的回调函数int(*cmp)(const void* e1,const void* e2))使用qsort()的参数width实现多类型的比较:cmp((char*)base + j*width,(char*)base+(j+1)*width) > 0))

Thinking 3.4

结合 load_icode_mapper 的参数以及二进制镜像的大小,考虑该函
数可能会面临哪几种复制的情况?你是否都考虑到了?

Thinking 3.5

你认为这里的 env_tf.pc 存储的是物理地址还是虚拟地址?

  • 物理地址。大概在0x400000+

你觉得entry_point其值对于每个进程是否一样?该如何理解这种统一或不同?

  • entry_point是一样的虚拟地址,但是进程PCB不同,可以映射到各自不同的物理地址。

Thinking 3.6

请查阅相关资料解释,上面提到的 epc 是什么?为什么要将env_tf.pc 设置为 epc 呢?

  • epc是发生异常中断时执行到的pc值,保存在curenv->env_tf.cp0_epc。
  • env_tf.pc保存进程上下文,pc保存了返回该进程时开始执行的pc值,即为发生异常时的epc

Thinking 3.7

操作系统在何时将什么内容存到了 TIMESTACK 区域

  • handle_int()处理时钟中断时,SAVE_ALL保存当前寄存器值的栈顶地址get_sp为0x8200_0000,即为TIMESTACK.

TIMESTACK 和 env_asm.S 中所定义的 KERNEL_SP 的含义有何不同

  • TIMESTACK是产生时钟中断异常时用的存放CPU寄存器状态的栈顶指针,KERNEL_SP是非时钟中断异常用的栈指针。

Thinking 3.8

试找出上述 5 个异常处理函数的具体实现位置。

  • genex.S中有 handle_int()的实现,有do_refill()即handle_tlb()的实现
  • syscall.S有handle_sys()的实现

Thinking 3.9

阅读 kclock_asm.S 和 genex.S 两个文件,并尝试说出 set_timer 和time_irq 函数中每行汇编代码的作用

    .text
LEAF(set_timer)
    li t0, 0xc8
    sb t0, 0xb5000100 
//实时钟绑定4号中断,触发4号中断

    sw    sp, KERNEL_SP 
//内核栈保存栈寄存器值

setup_c0_status STATUS_CU0|0x1001 0
//设置SR寄存器的状态:
//1.STATUS_CU0:打开CP0寄存器使用权
//2.SR[16]:IsC:软件能够访问并使指令高速缓存条目无效
//3.SR[4]:IEo

    jr ra
    nop
END(set_timer)


    .extern delay
timer_irq:
    sb zero, 0xb5000110
//关闭时钟中断
1:    j    sched_yield
//进程调度
    nop
    /*li t1, 0xff
    lw    t0, delay
    addu  t0, 1
    sw    t0, delay
    beq    t0,t1,1f    
    nop*/
    j    ret_from_exception
//异常返回
    nop

Thinking 3.10

阅读相关代码,思考操作系统是怎么根据时钟周期切换进程的。

二、实验难点与指导书反馈

  • 初始化进程目录时,没有理解为什么要复制UTOP上部分的内核目录,也不知道这部分的权限该如何设置。建议建议指导书把权限位的作用在头文件中指明,或者在lab教程中指明本实验中用到的权限位及其说明
  • 汇编代码读起来比较晦涩,可以把R3000中的一些部分的汇编知识抽离出来,辅助理解;比如:
    • SR寄存器各个位的作用。因为个人感觉虽然自己强硬地把R3000中那部分阅读翻译了一遍,但实际上还是比较困惑,不是很能读懂
    • 使用到的伪指令的作用。伪指令对阅读理解造成了比较大的理解障碍。
  • load_icode_mapper(),纠结了很久段尾要不要考虑和后面段的共享页面。希望指导书可以提前说明段按地址顺序由小到大加载,只用考虑段首的页面共用情况
  • de的第一个Bug就是load_elf()里面的binary地址,开始没有给binary+shdr_offset的段偏移
  • TIMESTACK和SP两个概念的辨析:这个思考题一开始卡住了,原因是grep -r TIMESTACK的时候没有查到汇编代码get_sp出现了0x8200_0000。
  • 可以强调一下INSERT_TAIL(env_sche_list,e,sche_link)要在env_create()而不是alloc时插入
  • 进程调度算法时为INSERT_TAIL

三、体会与感想

个人对Lab3的整体感受是比Lab2体验差很多。主要是以下原因:

  • 课下:
    • Lab2对存储管理的结构比较浑然一体,Lab3的知识相对零碎,比如很多变量的设置并不能直接看到其作用效果或范围,所以debug的时候也比较困难,比如Lab2debug还可以通过输出地址判断本步骤的正确性等,Lab3设计很多汇编函数和寄存器的操作,不管是理解还是测试都不是很容易
    • 从Lab3遇到Bug会比较瞻前顾后,不知道是本次Lab还是之前Lab的bug,排查Bug所在范围的过程比较头疼
  • 上机时的Exam和Extra题面都比较模糊,具体是以下几点:
    • Exam对于“版本号相同、ASID空闲”这一分支并未显式说明要分配此ASID,而另一分支显式说明“找到最小的未使用ASID并分配”,且还强调“不要做任何无关操作”,虽然按题意是要分配,但是在阅读上的体验并不好,会在是否需要分配的问题上绊住
    • Exam对于“模拟位图”和“运行进程”的界定可以更清晰些,避免歧义
    • Extra对PV操作资源的个数并未叙述清楚造成理解偏差
CATALOG
  1. 1. 一、实验思考题
    1. 1.1. Thinking 3.1
    2. 1.2. Thinking 3.2 结合 include/mmu.h 中的地址空间布局,思考 env_setup_vm 函数:
    3. 1.3. Thinking 3.3
    4. 1.4. Thinking 3.4
    5. 1.5. Thinking 3.5
    6. 1.6. Thinking 3.6
    7. 1.7. Thinking 3.7
    8. 1.8. Thinking 3.8
    9. 1.9. Thinking 3.9
    10. 1.10. Thinking 3.10
  2. 2. 二、实验难点与指导书反馈
  3. 3. 三、体会与感想