0%

MIT 6.S081笔记

01 Introduction and Examples

课程内容简介

OS purposes

  • Abstract H/W 硬件的抽象

  • Multiplex:在多个应用程序之间共用硬件资源。你可以在一个操作系统同时运行文本编辑器,程序编译器,多个数据库等等。操作系统能非常神奇的在不相互干扰的前提下,同时运行这些程序。这里通常被称为multiplex。

  • Isolation 进程之间隔离

  • Sharing 共享

  • Security 权限

  • Performance 性能

  • Range of uses 能够支持大量不同的用户场

system call

我们同时也对应用程序是如何与Kernel交互,它们之间的接口长什么样感兴趣。这里通常成为Kernel的API应用程序如何访问Kernel?通常来说,这里是通过所谓的系统调用(System Call)来完成

举几个例子

open

1
fd = open("out", 1);

比如open是一个系统调用,它会跳到Kernel,Kernel可以获取到open的参数,执行一些实现了open的Kernel代码,或许会与磁盘有一些交互,最后返回一个文件描述符对象fd。fd全称就是file descriptor。之后,应用程序可以使用这个文件描述符作为handle,来表示相应打开的文件。

write

1
write(fd, "hello\n", 6);

如果你想要向文件写入数据,相应的系统调用是write。你需要向write传递一个由open返回的文件描述符作为参数。你还需要向write传递一个指向要写入数据的指针(数据通常是char型序列),在C语言中,可以简单传递一个双引号表示的字符串(下图中的\n表示是换行)。第三个参数是你想要写入字符的数量。

第二个参数的指针,实际上是内存中的地址。所以这里实际上告诉内核,将内存中这个地址起始的6个字节数据写入到fd对应的文件中。

fork

1
pid = fork();

另一个你可能会用到的,更有意思的系统调用是fork。fork是一个这样的系统调用,它创建了一个与调用进程一模一样的新的进程,并返回新进程的process ID/pid。这里实际上会复杂的多,我们后面会有更多的介绍。

Why Hard and Interesting

学习操作系统比较难的另一个原因是,当你在设计一个操作系统时,你需要满足一些列矛盾的需求。

  • 其中一个是,你想要你的操作系统既高效又易用。高效通常意味着操作系统需要在离硬件近的low-level进行操作,而易用则要求操作系统为应用程序提供抽象的high-level可移植接口。所以,提供一个简单可移植,同时又高效的抽象接口需要一定的技巧。

  • 另一个矛盾的点是,我们想要提供一个非常强大的操作系统服务,这样操作系统才能分担运行应用程序的负担,所以我们需要强大的操作系统服务。但同时,我们也想要有简单的接口。我们不想程序员看到数量巨多,复杂且难以理解的的内核接口。因为,如果他们不理解这些接口,他们就会很难使用这些接口。所以,我们也想要简单的API。实际上是有可能提供既简单,同时又包含强大功能的接口。所以,这里要提供一个简单的接口,同时又包含了强大的功能。

  • 最后一个矛盾点是所有的操作系统需要满足的。你希望给与应用程序尽可能多的灵活性,你不会想要限制应用程序,所以你需要内核具备灵活的接口。但是另一方面,你的确需要在某种程度上限制应用程序,因为你会想要安全性。我们希望给程序员完全的自由,但是实际上又不能是真正的完全自由,因为我们不想要程序员能直接访问到硬件,干扰到其他的应用程序,或者干扰操作系统的行为。

操作系统提供了大量的特性和大量的服务,但是它们趋向于相互交互。有时,这种交互以奇怪的方式进行,并且需要你大量的思考。即使在我之前给出的一个简单例子中,对于open和fork,它们之间也可能有交互。如果一个应用程序通过open系统调用得到了一个文件描述符fd。之后这个应用程序调用了fork系统调用。fork的语义是创建一个当前进程的拷贝进程。而对于一个真正的拷贝进程,父进程中的文件描述符也必须存在且可用。所以在这里,一个通过open获得的文件描述符,与fork以这种有趣的方式进行交互。当然,你需要想明白,子进程是否能够访问到在fork之前创建的文件描述符fd。在我们要研究的操作系统中答案是,Yes,需要能够访问。

求大佬赏个饭