不落辰

知不可乎骤得,托遗响于悲风

0%

操作系统-xv6-lab总结

历时2月有余。完成了lab1-lab10。由于疫情遣返一堆事儿,故net-work lab只能有时间再做了。
不得不说,跟这门课真的是相见恨晚,之前不清不楚的知识点和机制,在阅读xv6的代码时都有了更为清晰的认知。
比如一个进程究竟是怎么被划分成用户线程和内核线程的?(内核进程:就是在内核维护了进程陷入内核后的函数调用栈)
比如页表究竟是如何运作的?我原先甚至都不知道页表还分成用户页表和内核页表,内核究竟是如何使用用户传入的虚拟地址的?(进程的内核页表中维护了用户的地址空间)
比如系统调用究竟是如何使得进程陷入内核的?通过trap,那么trap机制究竟是如何做到的?ecall -> trampoline -> 保存用户线程上下文(cpu regs)到结构体trapframe,加载trapframe之前保存的进程的内核线程的信息到cpu上,用户页表切换成内核页表,然后跳转到kernel C code usertrap。然后就是内核根据用户陷入内核的原因以及传入参数,通过一系列函数syscall实现系统调用。
比如进程切换究竟是如何实现的?内核究竟是如何调度不同进程的?内涵和为什么调度不了用户态线程?:内核中的上下文分为每个进程的内核线程,以及一个调度器线程。会有定时器中断等机制,使得os陷入内核,执行调度器线程,其会寻找一个runnable的内核线程(也即寻找一个runnbale的进程),然后运行该内核线程;该内核线程离开内核态时,os就会在用户态运行该进程的用户线程。如此,就实现了进程切换。这也解释了内核为什么不会调度同一个进程的用户态线程,因为内核的调度器线程只能看到进程的内核线程,看不到用户态线程。
比如用户究竟是如何拿到物理内存的?我们常说的malloc啥的,究竟是在那一层次做出的设计。
又比如常说的内核的buffer,是在哪里?是dram里吗?是,就是xv6中的bcache,所有和disk的交互都要通过bacche
又比如socket buffer,是在哪里?:有点忘了,大概是net.c通过kalloc申请出的一些内存用作socket buffer。
又比如lazy allocation? 是如何工作的?:先声明user的一段虚拟地址为合法但不建立映射,然后在用户第一次使用到该地址时,再通过pgfault陷入内核,在进程的user pagetable上为该地址建立虚拟地址到物理地址映射。
又比如cow 是如何实现的?: fork时假分配,哪些process先write,那些process cow真分配
又比如mmap 如何实现的 ? 为什么叫映射 ? 为什么高效 ? :基于lazy allocation实现. 高效: 直接映射到buffer
又比如文件系统