Operating Systems: Yet Another Three Easy Pieces
都是很抽象的大概念
用代码回答 “什么是操作系统上的程序”
状态 = $M$ (内存) + $R$ (寄存器)
初始状态
状态转移 = 时钟驱动的指令执行
这不是废话吗?有什么吗?
用处很多,
但今天主要讲代码
(程序 = 状态机)
int main() {
printf("Hello, World\n");
}
gcc 编译出来的文件不满足 “最小”
_start
)我们需要一个工具帮助我们
gdb!
starti
可以帮助我们从第一条指令开始执行程序start
会在 main
停下layout asm
可以更方便地查看汇编info registers
可以查看寄存器info registers
) + 内存 (pmap
)有办法让状态机 “停下来” 吗?
解决办法:交给操作系统
#include <sys/syscall.h>
int main() {
syscall(SYS_exit, 42);
}
movq $SYS_exit, %rax # exit(
movq $1, %rdi # status=1
syscall # );
我是从哪里获得这些黑科技代码的???
思考题:syscall 指令让状态机模型发生了什么变化?
为什么 Hello World 有颜色??
特殊编码的字符实现终端控制
telnet towel.blinkenlights.nl
(Ctrl-] and q 退出)dialog --msgbox 'Hello OS World!' 8 32
操作系统中同时运行多个程序,并维护 “操作系统定义” 的对象 (比如文件,包括可执行文件)。
程序 = 状态机 $(M, R)$
操作系统实现了资源的统一管理。
程序只能用操作系统允许的方式访问操作系统中的对象
Core Utilities (coreutils)
系统/工具程序
SDL2/SDL.h
其他各种应用程序
可执行文件 = 字节序列
vim
, cat
, xxd
等命令查看可执行文件vim
中打开,二进制的部分显示异常,但可以看到字符串常量 (例子:vim a.out
)xxd
可以看到文件以 "\x7f" "ELF"
开头解析可执行文件
/usr/include/elf.h
提供了必要的定义一个普通的 C 程序执行的第一条指令在哪里?
main
的第一条指令 ❌libc
的 _start
❌(gdb) starti
Starting program: /tmp/a.out
Program stopped.
0x00007ffff7dd6090 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0 0x00007ffff7dd6090 in _start () from /lib64/ld-linux-x86-64.so.2
#1 0x0000000000000001 in ?? ()
main()
之前发生了什么? (cont'd)readelf 告诉你答案。
进程初始时到 main()
执行时,进程的内存中多了 libc-2.27.so
ld-linux-x86-64.so
加载了 libcmain()
的开始/结束并不是整个程序的开始/结束
main 执行之前、执行中、执行后,
发生了哪些操作系统 API 调用 ?
呃……
In general, trace refers to the process of following anything from the beginning to the end. For example, the
traceroute
command follows each of the network hops as your computer connects to another computer.
这门课中很重要的工具:
strace ./hello-goodbye
(对部分初学者来说,会对这一点感到非常惊讶)
编译器 (gcc),代表其他工具程序
strace -f gcc a.c
(gcc 会启动其他进程)图形界面程序 (xedit),代表其他图形界面程序 (例如 vscode)
strace xedit
都在
本次课内容与目标
Take-away messages