操作系统笔记(一)
教材:Randal E. Bryant&David R. O`Hakkaron的深入理解计算机系统(第三版)
计算机系统漫游
程序编译过程
.c程序要被转化为可执行文件,并以二进制磁盘文件的形式存放起来。
过程由GCC编译器驱动程序完成:
GCC读取hello.c(源程序,文本) -> 经过预处理器(cpp),读取系统头文件内容并插入程序 -> hello.i(修改后源程序,文本) -> 经过编译器(ccl) -> hello.s(汇编程序,文本) -> 汇编器(as),翻译为机器语言指令 -> hello.o(可重定位目标程序,二进制) -> 链接器(ld),程序中调用的一些标准C库函数如printf -> hello(可执行目标程序,二进制)可加载到内存中,由系统执行
处理器读并解释存储在内存中的指令
系统的硬件组成
1.总线(传送定长的word)
2.I/O设备
每个IO设备都通过一个控制器或适配器与IO总线相连,前者是IO设备本身或者主板上的芯片组;后者是插在主板插槽上的卡
3.主存
临时存储设备,在处理器执行程序时,用来 存放程序和程序处理的数据。
从物理上说,主存是一组DRAM芯片组成的;逻辑上看,存储器是一个线性的字节数组,每个字节都有其唯一的地址(数组索引),地址从0开始。
4.处理器
中央处理器(CPU),解释(或执行存储在主存中指令的引擎)。处理器的核心是一个大小为一个字的存储设备(或寄存器),成为程序计数器(PC)。在任何时候,PC都指向主存中的某条机器语言指令(即含有该条指令的地址)。
运行hello程序
总之就是由主存中存储数据,CPU中的寄存器通过总线读写主存与外设获取数据后进行操作,最后再将REG中的数据要么存主存要么给IO
操作系统管理硬件
上图是计算机系统的分层视图。操作系统有两个基本功能:1.防止硬件被失控的应用程序滥用 2.向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。操作系统通过几个基本的抽象概念来实现这两个功能:进程,虚拟内存和文件
文件:对IO设备的抽象表示
虚拟内存:对主存和磁盘IO设备的抽象表示
进程:对处理器,主存和IO设备的抽象表示
进程
操作系统对一个正在运行的程序的一种抽象。
并发运行:看似同时,实则多进程分时占用CPU,通过处理器在进程间切换实现。该交错执行的机制成为上下文切换。
上下文:操作系统保持跟踪进程运行所需的所有状态信息,该状态称为上下文
从一个进程到另一个进程的转换是由操作系统内核管理的。内核是操作系统代码常驻主存的部分。当应用程序需要操作系统的某些操作时会执行系统调用指令,将控制权传递给内核,然后内核执行被请求的操作并返回应用程序。
线程
一个进程可由多个称为线程的执行单元(颗粒更小)组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。
虚拟内存
虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占地使用主存。每个进程看到的内存都是一致的,称为虚拟地址空间。图1-13所示的是Linux进程的虚拟地址空间(其他Unix系统的设计也与此类似)。在Linux中,地址空间最上面的区域是保留给操作系统中的代码和数据的,这对所有进程来说都是一样。地址空间的底部区域存放用户进程定义的代码和数据。请注意,图中的地址是从下往上增大的。每个进程看到的虚拟地址空间由大量准确定义的区构成,每个区都有专门的功能。
我们从最低的地址开始,逐步向上介绍。
程序代码和数据。 对所有的进程来说,代码是从同一固定地址开始,紧接着的是和C全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初始化的,在示例中就是可执行文件hello。
堆。 代码和数据区后紧随着的是运行时堆。代码和数据区在进程一开始运行时就被指定了大小,与此不同,当调用像malloc和free这样的C标准库函数时,堆可以在运行时动态地扩展和收缩。
共享库。大约在地址空间的中间部分是一块用来存放像C标准库和数学库这样的共享库的代码和数据的区域。
栈。 位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次我们调用一个函数时,栈就会增长;从一个函数返回时,栈就会收缩。
内核虚拟内存。 地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区域的内容或者直接调用内核代码定义的函数。相反,它们必须调用内核来执行这些操作。
虚拟内存的运作需要硬件和操作系统软件之间精密复杂的交互,包括对处理器生成的每个地址的硬件翻译。基本思想是把一个进程虚拟内存的内容存储在磁盘上,然后用主存作为磁盘的高速缓存。