OS Structures
Operating System Services¶

注:
- system call 就是 user space 和 kernel space 之间的桥梁
- 红圈内的就是为用户提供服务(抽象资源),蓝圈内的就是优化服务(分配资源)
User and Operating System-Interface¶
(略)
System Calls¶

解释:
1. printf 本质上就是 write 的一个 wrapper
2. write 函数(i.e. 上面的 __libc_write),里面有一个 syscall,将控制流从用户手中交给系统
3. 注意 %eax 为 1,因为 Linux x86 的 syscall 的 1 号就是 write

解释:进入 kernel space 之后,就做下面三件事
1. 无论如何,kernel_entry 的代码先会被执行
2. 然后根据传入的 %eax,从 syscall_table 中获取 ksys_write 的地址并 call
3. 在完成之后,执行 ret_to_user,并最终返回用户态
图示

syscall 的完整流程如上
Types of System Calls¶




System Services¶
(略)
Linkers and Loaders¶

注:中间缺了一个预处理环节
ELF Format¶
使用 readelf 查看 ELF 格式文件
readelf -S <file>:获取<file>的分区信息,各分区的(虚拟内存)地址、(文件中对应的)偏移量、权限等等readelf -s <file>:获取符号表,以及各符号的所在地址、所在分区编号、类型、名字等等readelf -p <section> <file>: Displays the contents of the indicated section as printable strings.readelf -x <section> <file>: Displays the contents of the indicated section as a hexadecimal bytes.

Answer to quiz:
1. 所有 const 都去 .rodata
2. 对于非 const,若已经初始化,就去 data
3. 若尚未初始化,就去 bss
如下图所示:

[Nr] Name Type Address Offset Flags
[15] .rodata PROGBITS 00000000000007e0 000007e0 AX
[22] .data PROGBITS 0000000000011000 00001000 WA
[23] .bss NOBITS 0000000000011014 00001014 WA
Note: A(alloc), X(execute), W(write)
Details of Loader¶

a.dynamic 就是动态编译(也是默认编译选项)的产物。其中 .interp 段指定了解释器。

Running a binary¶
对于动态加载库的 elf 文件,在操作系统上运行,初始化如下:

- Who setups ELF file mapping
- Kernel: exec
syscall
- Kernel: exec
- Who setups stack and heap
- Kernel: exec
syscall
- Kernel: exec
- Who setups libraries
- Loader:
ld-xxx
- Loader:
动态/静态链接的 syscall 对比
执行 a.dynamic 的时候,可以看到用到了 ld.so

至于 a.static(左图),相比 a.dynamic(右图),就会少很多各种加载

动态/静态链接的内存布局对比
a.static 如下,很干净:

a.dynamic 如下,在 heap 和 vvar 之间,有 libc 的动态链接库(不同虚拟内存,映射到同一个文件,但是权限不同);在 vdso 和 stack 之间,就是 loader 的动态链接库(同上)

动态/静态链接执行流程对比
如图:上面是静态,下面是动态。区别就一点:动态的时候,load_elf_binary 直接跳转至 loader 的起始地址(而不是二进制程序的起始地址)。
然后 loader 进行一通操作(i.e. mmap),将动态链接库文件(e.g. libc)映射到内存中,最后再跳至 _start。


Why Applications are Operating System Specific Operating-System Design and Implementation¶
Operating System Structure¶
TL;DR




Linux Kernel 一览
Different Kernels¶
- 宏内核(Monolithic Structure):各种 driver 等等辅助组件都在 kernel 内部,并且通过 privileged mode 运行
- PROS
- 速度快
- CONS
- 内核代码多,不易移植和扩展
- 如果 driver 在内核态运行过程中崩溃,那么就容易导致整个系统崩溃,稳定性差
- 安全性相对差
- PROS
- 微内核(Microkernel):不那么重要而 drivers,就不在 kernel 内部,并且在用户态下运行
- PROS
- 内核代码少,易于移植和扩展
- 尽量不在内核态中执行,稳定性好
- 安全性好
- CONS
- 由于很多模块位于用户态中,但是又必须通过
syscall来执行关键步骤、传递信息,因此调用链长,速度慢(如下图)
- 由于很多模块位于用户态中,但是又必须通过
- PROS
- hybrid kernel:前两者混合,取长补短
微内核调用链

Building and Booting an Operating System¶
(略,见 lab0)
Operating System Debugging¶
工具一览

Rules of thumb:
- Remember the separation of policy and mechanism
- log(包含
printk和 core dump 等等)为主,gdb 为辅 - 不要在代码中用 tricks,尽量多加注释、简洁明了
- 推荐工具
strace- trace system calls invoked by a processgdb- source-level debuggerperf- collection of Linux performance toolstcpdump- collects network packets