6.s081 学习笔记

笔记

2021年链接 https://pdos.csail.mit.edu/6.S081/2021/schedule.html

LEC 1

fork后子进程将复制父进程的数据段、BSS段、代码段、堆空间、栈空间和文件描述符

使用exec执行新的程序时,仍然可以使用原来的文件。

xv6 使用第一种方法。也就是子shell先关闭某个fd再打开,新fd取低值。

所以分开fork和exec的好处之一是可以重定向子进程(子shell的)IO然后再exec而不会扰乱主进程的文件描述符表。

fork以后的同一个文件描述符或者dup系统调用复制出来的文件描述符,他们对应的深层(underlying)IO对象都是一个,共享offset。

shell中有种常见的重定向2>&1,就是说fd 2(stderr)是fd 1(stdout)的副本,也就是错误和正常输出都到一块。

一个值得研读的重定向+pipe的例子:

关于xv6:ctrl+p打印进程信息,ctrl+a x退出qemu。

Lab Util

实现user/sleep.c,user/pingpong.c,user/primes.c,user/find.c,user/xargs.c,主要是完成这些工具。

LEC 3

操作系统三大需求:多路复用、隔离、交互。

宏内核monolithic kernel

RISC-V有三种模式,机器模式machine mode,监督模式supervisor mode,用户模式user mode

机器起于m mode,执行几条指令以后进入s mode。在s mode里面,cpu可以执行特权指令。如果u mode 的程序企图执行特权指令,那么不会执行,而是转为s mode并且停止程序。

u mode的程序运行于用户空间user space,s mode的程序运行于内核空间 kernel space,也称为内核kernel。

XV6为每个进程都维护了一个页表

每个进程都有用户栈和内核栈。执行用户指令时只用user stack,内核栈空。

系统调用使用ecall指令。

Lab Syscall

xv6进行系统调用

比方说我们在user/xxx.c里头写用户程序,调用了read()系统调用。这些系统调用的声明都在user/user.h中。

usys.pl是一个perl脚本,生成到usys.S里头形如

1
2
3
4
5
.global read
read:
li a7, SYS_read
ecall
ret

回想一下汇编语言,参数存在寄存器a0/a1……里头,a7加载上kernel/syscall.h里头定义好的标识数,ecall触发中断。

中断描述符到中断处理函数这里还没讲,反正就到了kernel/trap.c usertrap(),调用了kernel/syscall.c syscall(),处理了系统调用。

根据标识数和一个预先定义好的函数指针数组,来到了对应的系统调用处理函数kernel/sysfile.c sys_read()

这个函数没有入参,都是自己从寄存器里面捞出来的。它里面可能调用kernel/里头的其他函数。user/xxx.c并不能调用这些函数。

如果要写什么东西到用户内存,要使用copyout()。返回值的话,sys_read()的返回值存到a0里头(等同于eax)。

LEC 4

学到这里的时候和华科的os课设混着做了,感觉知识++

硬件三级页表:

虚拟空间$2^39$,物理空间$2^56$

快表TLB可以解决三级页表访存次数多的问题,但是记得切换进程的时候要清空tlb。

PTE(page table entry)有一些标记,PTE_V for valid, PTE_R/W之类的。

如果查的时候发现有不在的PTE,就发起缺页中断。

每个进程(CPU)都有自己的satp寄存器,存放根页表的地址。他们各自有各自的页表。并且,内核自己也有一个页表。

内核的虚拟空间

内核空间映射:

QEMU模拟的ram从kernbase到phystop。内核虚拟空间里,ram和底下的设备都是直接映射。

也有不是直接映射的:trampoline page(在虚拟空间的最高处,和用户页表一样,不过我不知道这是啥),以及内核栈页。每个进程都有一个内核栈。这些内核栈页直接都有guard page。

用户虚拟空间

代码片段

一个PTE是一个uint64,那么一个pagetable_t就是一个uint64的指针,,,

walk是走一遍三级页表,返回va对应的pte。期间可以指定是否分配不存在的页面。

空闲物理内存管理就是维护一个空闲页链表。一个页的下一个空闲页存放在这个页的最开头,用强制类型转换做。

LEC 5

trap有三种可能:

  • ecall
  • exception,例如除零
  • interrupt,例如io完毕