Mit6.s081---Lec01学习笔记
一、操作系统具有的一些共同目标
1、抽象硬件,实现高层次的接口和抽象,例如进程,文件系统,既方便了应用的开发,也提供了更好的移植性
2、在多个应用程序之间共用硬件资源,通常成为multiplex
3、isolation,即不同应用程序之间不会互相干扰
4、程序之间的数据共享,sharing
5、Security 或者 Access Control System
6、high performance
7、支持大量的用户场景 range of users
二、操作系统结构
分层的思想
有Userspace和Kernel
system call与function的区别:system call会跳到系统内核中
学生提问:系统调用跳到内核与标准的函数调用跳到另一个函数相比,区别是什么?
Robert教授:Kernel的代码总是有特殊的权限。当机器启动Kernel时,Kernel会有特殊的权限能直接访问各种各样的硬件,例如磁盘。而普通的用户程序是没有办法直接访问这些硬件的。所以,当你执行一个普通的函数调用时,你所调用的函数并没有对于硬件的特殊权限。然而,如果你触发系统调用到内核中,内核中的具体实现会具有这些特殊的权限,这样就能修改敏感的和被保护的硬件资源,比如访问硬件磁盘。我们之后会介绍更多有关的细节。
三、系统调用
read:接收3个参数,第一个是文件描述符,第二个是指向某段内存的指针,第三个是读取的最大长度,返回值是可能读到的最长长度
文件描述符本质上对应了内核中的一个表单数据。内核维护了每个运行进程的状态,内核会为每一个运行进程保存一个表单,表单的key是文件描述符。这个表单让内核知道,每个文件描述符对应的实际内容是什么。这里比较关键的点是,每个进程都有自己独立的文件描述符空间,所以如果运行了两个不同的程序,对应两个不同的进程,如果它们都打开一个文件,它们或许可以得到相同数字的文件描述符,但是因为内核为每个进程都维护了一个独立的文件描述符空间,这里相同数字的文件描述符可能会对应到不同的文件。
fork: fork会拷贝当前进程的内存,并创建一个新的进程,这里的内存包含了进程的指令和数据。之后,我们就有了两个拥有完全一样内存的进程。fork系统调用在两个进程中都会返回,在原始的进程中,fork系统调用会返回大于0的整数,这个是新创建进程的ID。而在新创建的进程中,fork系统调用会返回0。所以即使两个进程的内存是完全一样的,我们还是可以通过fork的返回值区分旧进程和新进程。特点(读时共享写时复制)
学生提问:fork产生的子进程是不是总是与父进程是一样的?它们有可能不一样吗?
Robert教授:在XV6中,除了fork的返回值,两个进程是一样的。两个进程的指令是一样的,数据是一样的,栈是一样的,同时,两个进程又有各自独立的地址空间,它们都认为自己的内存从0开始增长,但这里是不同的内存。 在一个更加复杂的操作系统,有一些细节我们现在并不关心,这些细节偶尔会导致父子进程不一致,但是在XV6中,父子进程除了fork的返回值,其他都是一样的。除了内存是一样的以外,文件描述符的表单也从父进程拷贝到子进程。所以如果父进程打开了一个文件,子进程可以看到同一个文件描述符,尽管子进程看到的是一个文件描述符的表单的拷贝。除了拷贝内存以外,fork还会拷贝文件描述符表单这一点还挺重要的,我们接下来会看到。
exec: 这个系统调用会从指定的文件中读取并加载指令,并替代当前调用进程的指令,从某种程度上来说,这样相当于丢弃了调用进程的内存,并开始执行新加载的指令。
有关exec系统调用,有一些重要的事情,
exec系统调用会保留当前的文件描述符表单。所以任何在exec系统调用之前的文件描述符,例如0,1,2等。它们在新的程序中表示相同的东西。
通常来说exec系统调用不会返回,因为exec会完全替换当前进程的内存,相当于当前进程不复存在了,所以exec系统调用已经没有地方能返回了。
wait:wait会等待之前创建的子进程退出,wait的参数status,是一种让退出的子进程以一个整数(32bit的数据)的格式与等待的父进程通信方式,status是内核向这个地址写入子进程向exit传递的参数