操作系统(实验班)预习笔记
Last updated on December 20, 2025 10:11 PM
0218
- Lab 代码量较大(几千行),需要注意实现 Design Doc
- TacOS:基于 Rust,指令集是 RISCV
- 本地测试点和测评测试点一致
- Design Doc 不用卷字数
- 五个 lab,两次考试(期中期末)
- 考勤 5%,Lab 30%,期中 25%,期末 40%
- lab:4% + 6.5% + 6.5% + 6.5% + 6.5%
0220
- 四个基本概念:线程、地址空间、进程、双模式
- CLAB 上部署 docker:
- pull taco 到本地
- 然后
docker save -o tacos.tar,再上传,在 CLAB 上docker load -l tacos.tar
0225 线程
- 线程上下文
- 同步:协调多个线程的运行使得对共享数据做操作的时候可以依照程序员期望的方式执行
- 锁的两个原子化状态:
lock.acquire()lock.release()
- 信号量 semaphore:更加 generailized 的锁
0228 文件
- POSIX 文件:
- data:二进制字节序列
- metadata:文件的信息
- 存储层次图:app -> high level I/O(流) -> low level I/O(描述符) -> Syscall -> File System -> I/O driver -> Disk/Flash/DMA
- high-level I/O:不带格式的字节流,以及文件位置
- fopen, fclose
- 预定义好的
FILE*流:stdin, stdout, stderr fseek操作文件位置,ftell返回文件位置,rewind返回到文件开头。
- low-level I/O:
- open before use:使用文件前必须打开
- byte-oriented
- kernel buffered read/write
- 显式关闭
open, close, creat。open 返回的是文件描述符。fopen等是在FILE*数据结构上操作的- 因为不能让用户态操作内核数据结构,所以不给指针,只给整数 fd
- 通过
fileno(FILE*)可以获取FILE*的 fd,通过fdopen可以将 fd 转换成FILE*
- I/O:
read, write,可能有不足值。lseek:重新调整文件位置,移动的是内核里的指针,不是应用层的。 - kernel buffing:内核会缓冲。进程阻塞,跑其他进程。
- high-level I/O:不带格式的字节流,以及文件位置
fread, fwrite是操作的 user space 的 buffer。kernel space 还有一个 buffer。low-level 的 API 就没有 user space 的 buffer 了。FILE*里面包含的东西:文件描述符,buffer 以及 lock- High-level 的意义:
- User buffer 的意义:减少系统调用次数(陷入内核需要上下文切换,效率低)
- 可以简化内核的实现:内核不需要实现什么读完一行的操作
- 打开文件表在内核里只维护一份。
- 一些陷阱:
- 不要在多线程里面
fork,除非你已经exec了。- fork 出来的新进程只会有一个线程(call fork 的线程)
- 而且不会做清理(锁,堆)
- 不要混合使用
FILE*和 fd
- 不要在多线程里面
0304 IPC
所有皆文件:进程间通信也用统一的 I/O 接口。socket 和 pipe。
PIPE:一个有限的内存中的 buffer。单向,producer 写,consumer 读。如果写的时候满了,阻塞;如果读的时候空的,阻塞。(但其实不一定要阻塞,只是一种方式)不需要显式创建文件
- 最后一个写描述符关掉后,读就只返回 EOF
- 最后一个读描述符关掉后,写的话会返回 SIGPIPE
进程间通信需要 syntax 和 semantics。一个协议可以通过状态机形式化表示(比如网络传送的一些字符串和数字,需要特定 translate)
RPC: remote procedure call
client-server 相对的:peer-to-peer。
TCP:两个进程间的双向进程流。一个连接有两个 buffer,独立的。
socket 也是抽象为了 fd,write 是往 output queue 里加东西,read 是从 input queue 取出东西。lseek 不适用。
一些假设:可靠性(TCP),保序(字节流)、像 pipe 一样有什么就读什么(假设已经写过了,像 pipe 一样)
剩下讲的东西都是 ICS 第 11 和 12 章讲的内容。
0306 SYNC 1
PCB:维护进程的状态,status, register state (when not ready), pid, 权限,执行时间,地址空间。
进程的状态:new,ready,running,waiting,terminated
调度就是从几个队列里面决定执行的顺序。没有 running 的进程 PCB 放到比如 I/O queue, ready queue 等等里面。
原则:公平性/实时性/延时优化等。
线程:共享堆、全局变量、代码。每个线程包含一个 TCB(栈,保存的寄存器状态,metadata),以及栈。线程调度伪代码:
1 | |
内核中:run_new_thread() -> switch()。