持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
什么是程序(源代码视角)
程序就是状态机
C程序的状态机模型
-
状态=堆+栈
-
初始状态的main的第一条语句
-
迁移=执行一条简单语句
- 任何C程序都可以改写成"非复合语句"的C代码
- 真的有这种工具和解释器
任何真正的理解都应该落到可以执行的代码
什么是程序(二进制代码视角)
状态=内存M+寄存器R
迁移=执行一条指令
调用指令syscall
-
把(M,R)完全交给操作系统,任其修改
-
实现与操作系统中的其他对象交互
- 读写文件/操作系统状态(例如把文件内容写入vi)
- 改变进程(运行中状态机)的状态,例如创建进程/销毁自己
t:对应用采说,操作系统可以看成一个函数,参数就是应用程序的当前状态,输出是应用程序要访问的资源。
进程的初始状态无法进行返回
如何创建一个最小的helloworld
解决异常退出
有办法让状态机“停下来”吗?
- 纯“计算”的状态机:不行
- 要么死循环,要么undefined behavior
解决办法:syscall
调试代码:syscall的实现在哪里?
- 坏消息:在libc里,不方便直接链接
- 好消息︰代码很短,而且似乎看懂了
这一部分打印helloworld
这一部分实现退出
综上所述:
程序=计算->syscall->计算->...
如何在程序的两个视角之间切换
可以直接将上述代码优化为g+=2
若是不想招上述优化
可以在不可优化部分加入memory
这样子中间部分会写入内存,因此第一个g++也会写入内存,因此无法与第二个g++串联,也就无法进行优化
操作系统中的一般程序
操作系统收编了所有的硬件/软件资源
-
只能用操作系统允许的方式访问操作系统中的对象
- 从而实现操作系统的“霸主”地位
- 例子: tryopen.c
-
这是为“管理多个状态机"所必须的
- 不能打架,谁有权限就给他
Trace
本质上,听有的程序和Hello world类似
程序=状态机=计算→syscall →计算→
-
被操作系统加载
- 通过另一个进程执行execve设置为初始状态
-
状态机执行
- 进程管理: fork, execve, exit,...
- 文件/设备管理:open, close, read, write,...
- ·存储管理:mmap, brk, ...
- 直到_exit (exit _group)退出 (初学者对这一点会感到有一点惊讶)
- 说好的浏览器、游戏、杀毒软件、病毒呢?都是这些API吗?
在应用的视角下,操作系统就是一条syscall指令
理解操作系统的重要工具:gcc,binutils,gdb,strace