我们经常利用各种 shell 命令(比如,cat,head),以及各种编程语言中IO方法(比如 go 中的 ioutil.ReadFile) 中的来读取文件,这些被封装好的接口调用起来很方便,但是他们的到底是怎么读取文件的呢?
我们来仔细看看这个四个字:读取文件。
先说什么是文件。要知道,文件是操作系统封装出来的一个概念。你可能会觉得文件是由硬盘管理的,但硬盘只知道自己身上存了一些磁性材料,不知道什么是文件。而且在 UNIX 系统中,很多文件根本就跟硬盘没有关系[1](我们有机会再谈)。不论是哪一种,操作系统中的“文件”最终都来自操作系统对于硬件的封装。
既然这个概念是由操作系统控制的,那么操作系统应该对”文件“有充分的解释权。于是,要想做到读取,很自然就会想到要和操作系统进行交互。
如果不考虑底层发生的事情,我们只看浅层的因果逻辑:输入命令,得到结果。
$ cat /path/to/file
you get contents in the file.
但刚刚我们已经说了,读取的过程中,一定会发生和操作系统的交互,这个交互到底是什么呢?
这里面会发生很多事情,但是我们一点一点的去探索。我们先来看稍微深层一点的逻辑(这个逻辑的细节适用于 POSIX 标准下的操作系统)。
- cat 会调用一个包含<unistd.h>库的 c 程序;这个库定义了 read 方法:
ssize_t read(int, void \*, size_t);
。 - c 程序调用 read 方法[2],read方法的底层执行一些操作系统中的方法,把要执行的 system call 用一个数字表示(比如 sys_read 对应的数字是 3),并存储在某个位置,比如一个寄存器中。
- 接下来运行 trap 指令,把进程的控制权交给 kernel。
- kernel 根据存下来的 system call 数字,找到对应的执行代码(handler),这个过程叫做 dispatch。
- handler 处理完成后(也就是,读取了特定字节后),进程控制权交回到user,把 read 方法中封装的其他操作执行完,然后开始执行 read 之后的程序,比如关闭文件。
这就是从 cat 指令开始,完成 read 这个 system call 的大致过程。
an illustration on system call但这里面有大量的细节其实还是没有讲清楚,比如
- cat 方法是怎么调用的 c 程序?
- system call 在不同的机器上实现方式不同,但是具体到某个机器上,是怎么实现的呢?
- trap 指令是什么指令?
- 以及这里的每一个技术名词,都需要仔细考察。
因此,我们把上面的过程再走一遍,但这次更近距离地观察,让更多的细节暴露出来。
- cat 程序开始执行,走着走着,来到了一个 c 程序中,这个 c 程序引入了一个叫做 unistd.h 的头文件
- 这个头文件是 POSIX 标准的一部分,里面定义了很多方法的调用方式,其中就有我们要用到的 read 方法——
ssize_t read(int, void \*, size_t);
- c 程序执行到了 read 方法那里。read 方法需要的 3 个参数先是被压入调用栈中,然后 read 方法开始执行
- 执行中的 read 方法调用了另外一个程序指令,把 sys_read 这个系统调用的编码查了出来(3),并把这个编码放在了一个寄存器中
- read 方法的定义中一定包含了一个 TRAP 指令。TRAP 指令的执行使得进程从 user mode 变为 kernel mode
- 进入到 kernel mode 的程序,要从哪里开始执行呢?TRAP 指令会给出一个特定的地址,操作系统就从那里读取下一条指令
- 操作系统读取到这条被指定的指令,从而开始以下工作:从寄存器中查出系统调用的编码,并根据这个编码找到下一步要去调用哪些代码(这一步叫做 dispatch,发送的意思)
- 这些被调用的代码叫做 handler,他实际完成读去文件的操作
- 完成读取之后,进程返回到 user mode,继续执行 TRAP 之后的指令,知道完成 read 方法
- read 方法已经完成,指定被压入调用栈的 3 个参数现在用不到了,他们会被移除
- 然后,程序可以执行 c 程序中的下一段代码了
这个观察更仔细的版本,部分解决了我们之前一个问题:TRAP 指令是什么。总结一下就是,TRAP 指令是一个让进程进入 kernel mode,并且只能指定特定的内存地址让计算机去找下一条指令。其他方面,他和普通的计算机指令是差不多的。
当然,我们还可以有更深入的版本,这条追查的路,可以一路深入到物理和数学的层面(电子和计算)。但今天,对于我们目的:认识一个系统调用的例子,已经起到了一定的作用。
下次,我们会研究 read 之外其他的一些系统调用。
-
modern operating system, page.44 ↩
网友评论