1803 字
9 分钟
Lec01:Introduction and Examples (Robert)
Lec01:Introduction and Examples (Robert)
操作系统的目标
- Abstraction
- multiplex
- Isolation
- Sharing
- Security
- Performance
- Range of userd
- 第一个就是抽象硬件。通常来说,你会买一个计算机,里面包含了CPU,内存,但是这是一种非常低层级的资源。幸好我们有一些应用程序实现了高层级的接口和抽象,例如进程,文件系统。这些高层级的接口和抽象(Abstraction)方便了应用的开发,也提供了更好的移植性。
- 操作系统的另一个重要的任务是:在多个应用程序之间共用硬件资源。你可以在一个操作系统同时运行文本编辑器,程序编译器,多个数据库等等。操作系统能非常神奇的在不相互干扰的前提下,同时运行这些程序。这里通常被称为multiplex。
- 因为在操作系统中可能同时运行很多程序,即使程序出现了故障,多个程序之间互不干扰就变得非常重要。所以这里需要隔离性(Isolation),不同的活动之间不能相互干扰。
- 但是另一方面,不同的活动之间有时又想要相互影响,比如说数据交互,协同完成任务等。举个例子,我通过文本编辑器创建了一个文件,并且我希望我的编译器能读取文件,我绝对想要数据能共享。所以,我们希望能在需要的时候实现共享(Sharing)。
- 但是在很多场景下,用户并不想要共享,比如你登录到了一个公共的计算机,例如Athena,你不会想要其他人来读取你的文件。所以在共享的同时,我们也希望在没有必要的时候不共享。这里我们称为Security或者Permission System或者是Access Control System。
- 另一个人们认为操作系统应该具有的价值是:如果你在硬件上花费了大量的金钱,你会期望你的应用程序拥有硬件应该提供的完整性能,但是很多时候你只负责应用程序编程,你会期望操作系统也必须保证自身提供的服务不会阻止应用程序获得高性能。所以操作系统需要至少不阻止应用程序获得高性能,甚至需要帮助应用程序获得高性能(Performance)。
- 最后,对于大部分操作系统,必须要支持大量不同类型的应用程序,或许这是一个笔记本,正在运行文本编辑器,正在运行游戏,或许你的操作系统需要支持数据库服务器和云计算。通常来说,设计并构造一个操作系统代价是非常大的,所以人们总是希望在相同的操作系统上,例如Linux,运行大量的任务。我认为大部分人都已经跑过Linux,并使用了我刚刚描述的所有的场景。所以,同一个操作系统需要能够支持大量不同的用户场景。
操作系统架构
文件描述符
内核为每个进程维护一张文件描述符表
文件描述符本质上对应了内核中的一个表单数据。
内核维护了每个运行进程的状态,内核会为每一个运行进程保存一个表单,表单的key是文件描述符。这个表单让内核知道,每个文件描述符对应的实际内容是什么。
关键:每个进程都有自己独立的文件描述符空间,所以如果运行了两个不同的程序,对应两个不同的进程,如果它们都打开一个文件,它们可能得到相同数字的文件描述符,但是因为内核为每个进程都维护了一个独立的文件描述符空间,这里相同数字的文件描述符可能会对应到不同的文件。
-----> 意思就是不同进程打开同一个文件,在进程内对指向这个文件的文件描述符可能不同
关于 exec 一些注意点
有关exec系统调用,有一些重要的事情,
- exec系统调用会保留当前的文件描述符表单。所以任何在exec系统调用之前的文件描述符,例如0,1,2等。它们在新的程序中表示相同的东西。
- 通常来说exec系统调用不会返回,因为exec会完全替换当前进程的内存,相当于当前进程不复存在了,所以exec系统调用已经没有地方能返回了。
为什么 exec 保留文件描述符表
当 exec 系统调用执行时,它确实会替换当前进程的代码段、数据段和堆栈等,但是操作系统默认情况下会保留文件描述符表。这样做的主要原因包括:
- 允许数据持续传输**:进程在调用 exec 前可能已经打开了一些重要的文件、网络连接或其他资源,并且可能需要在新加载的程序中继续使用这些资源。例如,标准输入、输出和错误(文件描述符0、1、2)通常需要在程序执行期间持续有效,以便新程序可以继续使用标准的输入输出流。**
- 简化程序设计**:程序员可以在 exec 前预先配置文件描述符,然后无需在新程序中重新进行繁琐的设置。这降低了程序复杂性,提高了代码的复用性。**
- 避免资源泄露:自动保留文件描述符意味着这些文件描述符在 exec 后仍然被正确管理,而不是被无意中关闭,从而避免了资源泄露。
fork和exec分离的好处(I/O 重定向)
以下是一个 redirect 代码,运行了 echo,但在 echo 输出前,重定向了****文件描述符1。
解释:
- 我们在第13行fork 一个子进程。
- 然后在子进程中改变了文件描述符。文件描述符1通常是进程用来作为输出的(也就是console的输出文件符)Shell会将文件描述符1改为output文件,之后再运行你的指令。
- 同时,父进程的文件描述符1并没有改变。所以这里先fork,再更改子进程的文件描述符,再执行 echo 来输出。这是Unix中的常见的用来重定向指令的输入输出的方法,这种方法同时又不会影响父进程的输入输出。因为我们不会想要重定向Shell的输出,我们只想重定向子进程的输出。
- 这样运行redirect程序后,shell 中可以看到没有任何的输出。但是实际上redirect程序里面运行了echo,只是echo的输出重定向到了output.txt。
这就是fork和exec分离的好处,我们可以在 fork 之后 exec 之前配置一些关键信息。
Lec01:Introduction and Examples (Robert)
https://scudays.github.io/posts/6s081/lecture/lec01introduction-and-examples-robert/