目录
上一篇讲解了hello程序在计算机系统中是如何运行的。hello 程序的机器指令最初是存放在磁盘上的,当程序加载时,他们被复制到主存;当处理器运行程序的时候,指令又从主存复制到处理器。相似的,数据串"Hello World" 初始时在磁盘上,然后复制到主存,最后从主存上复制到显示设备。
针对数据复制所引起的开销,系统设计者更小更快的存储设备——高速缓存存储器(cache/高速缓存)
1.高速缓存存储器(cache)
更小更快的存储设备
暂时的集结区域,用来存放处理器近期可能会需要的信息
2.存储器层次结构
2.1遵循的机械原理
较大的存储设备比较小的存储设备运行的慢,而快速设备的造价远高于同类的低速设备
2.2主要思想
上一层的存储器作为低一层存储器的高速缓存,因此,寄存器文件就是L1的高速缓存,L1是L2的高速缓存,L3是主存的高速缓存,而主存又是磁盘的高速缓存
3.操作系统
当外壳加载和运行 hello 程序,以及 hello 程序输出自己的消息时,外壳和 hello 程序都没有直接访问键盘、显示器、磁盘或者主存。取而代之的是,它们依靠操作系统提供服务。
那么什么是操作系统呢?我们可以把操作系统看成应用程序和硬件之间插入的一层软件,如下图:
3.1两个基本功能
①、防止硬件被失控的应用程序滥用。
②、向应用程序提供简单一致的机制来控制复杂而又大相径庭的低级硬件设备。
3.2实现基本功能引出的抽象概念
如上图:文件是对I/O设备的抽象表示,虚拟存储器是对主存和磁盘I/O设备的抽象表示,进程则是对处理器、主存和I/O设备的抽象表示。
3.2.1进程(第八章解释实现原理)
概念:操作系统对一个正在运行的程序的一种抽象,在一个系统上可以运行多个进程,而每个进程都好像在独占的使用硬件
操作系统的假象:运行一个程序时,感觉系统只运行这一个程序即系统存储器中唯一的对象
实际上:他们是并发的在运行,即一个进程的指令和另一个进程的指令是交错运行的。
单CPU系统中:一个时刻只能运行一个进程
多CPU系统中:能够同时处理多个进程。
但无论是单核还是多核,一个CPU只能并发的执行多个进程,这是通过处理器在进程间切换来实现的。而操作系统实现这种交错机制称为上下文切换。
上下文:操作系统保持跟踪进程运行所需的所有状态信息,比如PC和寄存器文件的当前值,主存的内容。
上面的A进程是外壳进程,B进程是hello进程。起初只有外壳进程在运行,即等待命令行上的输入,当我们输入相关命令让它运行hello程序时,外壳通过调用一个专门的函数,即系统调用,来执行我们的请求,系统会将控制权传递给操作系统。操作系统保存外壳程序的上下文,创建一个新的 hello 进程以及上下文,然后将控制权传递给新的 hello 进程。hello 进程终止后,操作系统恢复外壳进程的上下文,并将控制权回传给它,外壳程序将继续等待下一个命令行输入。
实现进程这种抽象概念需要低级硬件和操作系统软件之间的紧密合作,这个实现原理以及应用程序如何创建和控制它们的进程的呢?第八章解释
3.2.2线程
程序执行流的最小单元
一个进程由多个称为线程的执行单位构成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据,多线程之间比多进程之间高效,多线程更容易共享数据
3.2.3虚拟内存(第九章解释)
进程的假象:即每个进程都在独占的使用主存。
每个进程看到的内存是一致的,称虚拟地址空间
在Linux系统中,地址空间最上面的区域是为操作系统中的代码和数据保留的,这对所有进程是一致的。地址空间的底部区域存放用户进程定义的代码和数据。上图的地址从下往上是增大的。
我们从最低的地址,逐步向上介绍上面出现的区域名词。
①、程序代码和数据:对于所有进程来说,代码是从同一固定地址开始,紧接着是全局变量相对应的数据位置。直接按照可执行目标文件的内容进行初始化。(第七章)
②、堆:代码和数据区后紧随的是运行时堆。代码和数据区是在进程一开始运行时就规定了大小,而当调用malloc和free这样的 C 标准库函数 时,堆可以在运行时动态的扩展和收缩。(第九章)
③、共享库:存放像C标准库和数据库这样的代码和数据的区域。(第七章)
④、栈:位于用户虚拟地址空间顶部,编译器用它来实现函数调用,用户栈在程序执行期间可以动态的扩展和收缩。当我们调用一个函数时,栈会增长;从一个函数返回时,栈会收缩。(第三章)
⑤、内核虚拟内存:内核总是驻留在内存中,是操作系统的一部分,不允许应用程序读写这个区域的内容或者直接调用内核代码定义的函数。
3.2.4文件
文件就是字节序列,即由值0和值1组成的序列。所有的I/O设备,包括磁盘、键盘、鼠标、显示器都可以看成是文件。
好处
1.统一了系统中所有的I/O设备
2.同一个程序可以使用不同磁盘技术的不同系统运行
4.计算机系统中抽象的重要性
抽象的使用是计算机科学中最重要的概念之一。例如,为一组函数规定一个简单的应用程序接口API就是一个很好的编程习惯。程序员无需了解它内部的工作原理便可以使用这些代码。这在Java当中的典型比如类的定义,C语言中的函数原型。
4.1常见的抽象
文件:对I/O设备的抽象
虚拟内存:对程序存储器的抽象
进程:一个正在运行的程序的抽象
虚拟机:对整个计算机的抽象,包括操作系统,处理器和程序
指令集架构:对实际处理器硬件的抽象