NJUOS-2-操作系统上的程序
本文最后更新于:2 年前
JYY第二课:操作系统上的程序
JYY是我的男神!!!
状态机与数字电路
状态机的逻辑
1 |
|
REGS_FOREACH这个是一个小的语法特性,查看小技巧昂!!!
上面就类似于一个晶体管 -> 如果用管道连到对应的Python程序,甚至可以图形化界面类似于晶体管输出,就很方便昂!
什么是程序(程序视角)
- 数字系统就是状态机,程序运行在数字系统中 -> 程序也是状态机。
- C语言也是状态机:
- 状态 = 栈 + 堆
- 初始状态 = main的第一条语句
- 迁移 = 执行一条简单的语句
- 任何C程序都可以改写成“非复合语句”的C代码
- 有这种工具
任何真正的理解都应该落实到可以执行的代码
- 函数调用/返回无非就是stack frame,栈的改变嘛
对于每一种语句,都写出状态机是如何变动的行为 -> 拨开递归,自己去迭代创建stack frame,弹出stack frame等
程序就是一个状态机,每一步都是状态,我们完全可以根据程序的语句,操纵程序的行为 -> 从一个状态转变为另外一个状态。
可执行文件视角
本质也是状态机啊,更加底层昂!!!随机数怎么办呢? -> 状态机有多个分叉:
程序理解:状态转移!死循环就是状态转移嘛…又回到当初了呢!
- 操作系统上的程序:
- 绝大多数的指令只能计算 -> 状态机状态转移
- 特殊的指令syscall -> 将当前的所有状态(M, R)无条件交给操作系统 -> 操作系统可以对于当前状态做任何事,接替程序执行,想杀了就杀了,返回一个全新的(M’, R’),操作系统帮助我们更改状态机,system call就是程序和操作系统交互的接口。
- 程序 = 计算 + syscall(操作系统调用)
构造一个最小的hello world程序
1 |
|
1 |
|
- 直接编译可以看到,其实转换成的代码不长orz -> 使用ld命令去进行链接:
gcc -c main.c + ld
1 |
|
gdb找不到_printf… -> 因为没有环境变量之类的东西。gdb调试之后,发现可以被操作系统处理,但是出错了…,程序while(1)都可以正常执行。
报错,错误退出。GDB去调查,到底哪里的数据 or 堆栈寄了 -> 发现某个寄存器,访问不到哇orz。异常退出 -> 正常退出。syscall:
1 |
|
追踪发现:这里执行syscall的时候,无非是给各种寄存器赋值(M, R)。然后调用syscall,让系统进行处理。
如何在程序的两个视角之间切换
汇编 和 C的视角切换
C视角(Source) -> 汇编视角(Assembly code)
C = compile(S)
- 什么是编译器:
- 程序的状态机中,可能包含,可以优化的部分,和不能优化的部分。
- 正确的编译:S和C的可观测行为严格一致!!!C对应的状态机 -> 汇编对应的状态机,C代码中不可优化的部分全部被正确翻译到汇编上!
- 因此就有优化空间,怎样去理解这些semantics,并进行编译的优化,正确,精准且快速的编译!!!
- 编译器优化例子:
即使上面这种情况,编译器依然十分聪明的进行了优化。。。
- 不可优化?
程序合成:编译器先去理解我的代码的意思,再去等价生成小而精简的汇编代码(or other codes)
- 程序本质就是:计算 + syscall
- 应用眼睛里看到的操作系统,就是system call,也就是API。因此集中管理了所有的软硬件的资源。 -> 操作系统就是一个系统调用。
等价于在问,操作系统给这个进程/程序的初始状态是什么?
- strace工具:
操作系统不神秘,strace可以看任意的状态昂!!!
小技巧
REGS_FOREACH,参见上面,可以定义一个_函数,对于某些变量做操作!!!
Gcc -E xxx.c -> 把上面的宏展开,变成简单的简洁的代码:
- C语言中的#include的语意本质就是复制粘贴,把我们引入的内容直接粘贴到对应的文件中。
- gcc -c verbose可以看到诊断结果,gcc -static可以静态编译,不需要动态链接库 -> 程序就会大一些。gcc -c -> compile only,这个时候就会小很多昂!!!
- compile only出来的结果,可以通过ld去尝试直接链接这段代码 -> 可能一些库里支持的操作(包含操作系统调用),由于纯编译,导致ld去链接的时候,用不了!!!
- GDB很好用!!!汇编代码和C代码,都可以进行打断点处理!!!!! -> 可以去看看文档昂!!!
- 这里的一点小测试:
1 |
|
1 |
|
- man sys call -> 可以看到各种sys call调用的环境,变量,以及使用昂!对照着手册,才能正常使用昂!
- strace工具可以看到操作系统上,某个程序执行的所有的调用。
References
objdump link: https://ivanzz1001.github.io/records/post/linux/2018/04/09/linux-objdump
GCC & GDB(非常多的宝藏!!!): https://sourceware.org/