#### 概述

操作系统是用户和硬件之间的桥梁，它把硬件抽象为一些接口，以供用户使用。接口，即系统调用接口。xv6的接口主要包含两方面的抽象：进程和文件。

进程要占用CPU，要有自己的内存。所以，我觉得可以把进程看作是对CPU和内存的抽象。

文件则可以看作是对外设和外存的抽象。文件在元数据里标示自己是什么硬件。

进程和文件的关系：

- 每个进程都有自己的文件描述符来操作文件。
- 文件是程序的载体。

#### 内核和用户通过接口进行交互

内核启动的时候，先从`_entry`开始执行，目的是为C的执行建立环境。然后跳转到C代码`start`，目的是初始化时钟控制器并切换到内核态。切换到内核态后，开始执行`main`，目的是调整硬件的状态并用一些数据结构来记录这些硬件(硬件抽象化)。

`main`调用`userinit`来创建第一个用户进程，即著名的`init`进程(0号进程)，它是所有其它用户进程的祖先进程。`init`进程是在用户态还是内核态呢？它是在用户态的，因为`userinit`调用的`allocproc`通过设置内核栈和寄存器，使得进程运行时会“返回”到用户空间。`init`进程的源码包括`user/initcode.S`和`user/init.c`，`userinit`把`initcode.S`的二进制复制进内存，`initcode.S`利用`exec`执行`init.c`编译后的镜像。`init`进程是永不退出的，它干两件事：开启shell，处理僵尸进程。

`init`进程调用`fork`和`exec`来创建第二个用户进程，即shell，它是1号进程。shell做的事就是用`getcmd`来获取输入，用`fork`来创建子进程，子进程用`runcmd`来执行用户的输入，父进程shell则执行`wait`来等待子进程退出，然后一直重复这样的循环。

用户可在`user/user.h`看到系统调用接口，它们用户态实现在`user/usys.S`。当执行`ecall`指令后，CPU进到内核态，从`stvec`保存的地址开始执行。对于内核态的用户进程来说，它的`stvec`保存的是`uservec`的地址。`uservec`跳转到`usertrap`，`usertrap`调用`syscall`。`syscall`将依据之前的系统调用号执行具体的系统调用函数。这些具体的系统调用函数定义在`sysfile.c`和`sysproc.c`里，这也从一个侧面显示了进程和文件确实是操作系统提供的核心抽象。`usertrap`最后会调用`usertrapret`，`usertrapret`又跳转到`userret`，`userret`使用`sret`指令返回用户空间。

#### 进程和内存

- 进程的创建

  当前进程通过`fork`创建一个子进程，子进程的大部分内容和父进程是一样的。子进程执行`exec`来把它真正要执行的程序替换进子进程并执行之。

- 进程退出

  当前进程通过执行`exit`停止运行并释放资源。要停止其它进程用`kill`。

- 等待子进程退出

  父进程可能需要通过`wait`等待子进程退出，以执行其它的操作。

- 当前进程睡眠

  `sleep`

- 分配或回收内存

  `sbrk`

- 其它

  `getpid`获取当前进程的进程号，`uptime`获取开机后时钟中断发生的次数。

#### 文件系统

##### 文件描述符

进程通过文件描述符操作文件，文件描述符是独属于每个进程的私有变量。每个进程的文件描述符都从0开始编号，当进程创建的时候它的前3个文件描述符就被分配了，它们分别代表：0标准输入，1标准输出，2标准错误。在进程控制块里有一个数组记录了打开文件的指针，文件描述符就是打开文件在这个数组里的编号。打开文件的指针是指向哪里的呢？系统里所有的打开文件都在结构体`ftable`里，打开文件的指针都是指向`ftable`里的某个元素。

- 操作文件描述符

  `read`和`write`从文件描述符指向的文件读或写指定长度的字节。`close`释放一个文件描述符，`dup`是为一个已有的文件描述符的底层实体分配一个新的文件描述符。

##### 管道

`pipe`用于创建管道，管道是内核里的一块小的缓冲区，用于进程间通信。`pipe`分配了两个文件描述符，一个用于读另一个用于写，两个进程分别持有这两个文件描述符就可以单向通信了。

##### 数据文件和目录

数据文件就是一个字符数组。目录也是一种数据文件，它记录的是其它数据文件或目录的位置。之前所说的文件描述符是更高级别的抽象，它的包括了数据文件、设备和管道。目录是一个粘合剂，把所有文件组织成了一个树状结构。这个树里的某条线段就是一个路径。路径可以从根目录开始，叫绝对路径。也可以从当前目录开始，叫相对路径。

- 操作目录

  `chdir`用于改变当前目录。`mkdir`用于创建目录。

- 操作文件

  `open`可以用来创建一个数据文件。`mknod`用来创建一个设备文件。`link`给已有的索引结点再创建一个文件名。`unlink`给索引结点移除一个文件名，当索引结点的链接数和引用记数都为0，表明最后一个文件被删除了且没有进程在使用它，那个索引结点和它对应的磁盘空间会被释放。

- 其它

  `fstat`用于获取索引结点的元信息。

