A fork() in the road
本文最后更新于:2024年8月11日
本文是A fork() in the road的读书笔记
作者认为,fork 作为操作系统原语阻碍了系统研究;作为教育工作者,应该把 fork 当作历史的产物来教,而不是学生遇到的第一个进程创建机制。
fork 有一些优点:
- 简洁
- 避免并发,当然是在有线程和异步之前。
作为一个存在了50年的抽象,在当今fork也有很多缺点:
fork 已经不再简洁了,如果只有内存和文件描述符,这是十分优雅的方案,但是操作系统的演化过程中,进程增加了更多的东西。如今 POSIX 标准列出了 fork 的25种特殊情况,包括文件锁,tracing 等等。
Fork doesn’t compose。不适用于用户空间的很多抽象,比如说 Buffered IO
1
2
3
4for (int i = 0; i < 2; i++) {
fork();
printf("Hello\n");
}在笔者的电脑上(ubuntu 22.04)直接运行该程序会输出6行
Hello
,但是管道给wc -l
后结果是8 具体可以看jyy在B站的视频讲解线程安全问题。比如某个线程使用 malloc 获取到了堆区的锁,这个时候 fork,子进程一旦调用 malloc ,就会死锁。
安全性,子进程会继承父进程的每一个字节
性能低, copy-on-write 能够一定程度上解决这个问题,但是如今创建 copy-on-write 的映射也会造成一定程度的性能开销。
可扩展性,fork需要复制状态机的每个方面,这意味着实现fork需要统一管理系统状态,这在宏内核里很容易实现,但是微内核中这很难。
Fork encourages memory overcommit。作者认为,fork 时并不会请求所有的内存,而是 copy-on-write 复用父进程的内存,需要修改时再申请,这样会造成意料之外的 oom
fork 并不适用于单地址空间,并且 fork 影响了很多并不基于 unix 系统的科研系统,他们要考虑是否实现fork 语义,若实现,则很可能影响其原有的设计,束缚原先的设计。
fork 不适用于异构设备,毕竟没办法复制异构设备的状态。
fork 会感染一整个系统,需要每一个层次都支持 fork
作者认为,shell 很适合使用 fork,但是大多数的现代应用并不是 fork
作者最后提出了一些愿景:
- 弃用 fork
- 改进比如 posix_spawn() 这样的替代品
- 修改教学,就像没有人会在一开始教授
goto
,我们也不应该讲授如何使用fork
创建进程