{dy}章计算机系统漫游_铤而走险的兔子的空间_百度空间
在Unix系统上,从源文件到目标文件的转化是由编译器驱动程序(compiler drivers)完成的:
unix-> gcc -o hello hello.c
在这里,gcc编译器驱动程序读取源程序文件hello.c,并把它翻译成一个可执行目标文件hello。这个翻译的过程是分为4个阶段完成的。执行这4个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统。
预处理阶段。预处理器(cpp)根据以字符#开头的命令(directives),修改原始的C程序。结果得到另一个C程序,通常是以.i作为文件扩展名。
编译阶段。编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。
汇编阶段。接下来,汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包称为一种叫做可重定位(relocatable)目标程序的格式,并将结果保存在目标文件helloo中。
链接阶段。我们的hello程序调用了printf函数,它是标准C库中的一个函数,每个C编译器都提供。printf函数存在于一个名为printf.o的单独的预编译目标文件中,而这个文件必须以某种方式并入到我们的hello.o程序中。连接器(ld)就负责处理这种并入,结果就得到hello文件,它是一个可执行目标文件(简称可执行文件)。可执行文件加载到存储器后,由系统负责执行。

系统的硬件组成。
总线。贯穿整个系统的是一组电子管道,称作总线,它携带信息字节并负责在各个部件间传递。通常总线被设计成传送定长的字节块,也就是字(word)字中的字节数(即字长)是一个基本的系统参数,各个系统中不尽相同。
I/O设备。I/O设备是系统与外界的联系通道。每个I/O设备都是通过一个控制器或适配器与I/O总线连接起来的。控制器和适配器之间的区别主要在于它们的组成方式。控制器是I/O设备本身中或是系统的主印刷电路板上的芯片组,而适配器则是一块插在主板插槽上的卡。
主存。主存是以一个临时存储设备,在处理器执行程序时,它被用来存放程序和程序处理的数据。物理上来说,主存是由一组DRAM(动态随机访问存储器)芯片组成的。逻辑上来说,存储器是由一个线性的字节数组组成的,每个字节都有自己{wy}的地址(数组索引),这些地址是从零开始的。
处理器。中央处理单元(CPU)简称处理器,是解释(或执行)存储在主存中指令的引擎。处理器的核心是一个被称为程序计数器(PC)的字长大小的存储设备[或寄存器(register)]。在任何一个时间点上,PC都指向主存中的某条机器语言指令(内含其地址)。CPU在指令的要求下可能会执行这些操作:
加载:从主存拷贝一个字节或者一个字到寄存器,覆盖寄存器原来的内容。
存储:从寄存器拷贝一个字节或者一个字到主存的某个位置,覆盖这个位置上原来的内容。
更新:拷贝来年各个寄存器的内容到ALU,ALU将两个字相加,并将结果存放到一个寄存器中,覆盖该寄存器中原来的内容。
I/O读:从一个I/O设备中拷贝一个字节或者一个字到一个寄存器。
I/O写:从一个寄存器中拷贝一个字节或者一个字到一个I/O设备。
跳转:从指令本身中抽取一个字,并将这个字拷贝到程序计数器(PC)中,覆盖PC中原来的值。

在处理器和一个较大较慢的设备(例如主存)之间插入一个更小、更快的存储设备(例如,高速缓存存储器)的想法称为一个普遍的观念。
存储器分层结构的主要思想是一个层次上的存储器作为下一层次上的存储器的高速缓存。

我们可以把操作系统看成是应用程序和硬件之间插入的一层软件。
操作系统主要有两个用途:放置硬件被失控的应用程序滥用;在复杂控制而又通常广泛不同的低级硬件设备方面,为应用程序提供简单一致的方法。
操作系统通过几个基本的抽象概念(进程、虚拟存储器和文件)实现这两个用途。文件是对I/O设备的抽象表示,虚拟存储器是对主存和磁盘I/O设备的抽象表示,进程则是对处理器、主存和I/O设备的抽象表示。

进程是操作系统对运行程序的一种抽象。在一个系统上可以同时运行多个进程,而每个进程好像在独占地使用硬件。我们称之为并发运行,实际上是说一个进程的指令和另一个进程的指令时交错执行的。操作系统实现这种交错执行的机制成为上下文切换(context switching)。
操作系统保存进程运行所需的所有状态信息。这种状态,也就是上下文,包括许多信息,比如PC和寄存器堆的当前值,以及主存的内容。在任何一个时刻,系统上都只有一个进程正在运行。当操作系统决定从当前进程转移控制权到某个新进程时,它就会进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权转移到新进程。新进程就会从它上次停止的地方开始。
实现进程这个抽象概念需要低级硬件和操作系统软件的紧密合作。

尽管通常我们认为一个进程只有单一的控制流,但是在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。由于网络服务器中对并行处理的要求,线程成为越来越重要的编程模型,因为多线程之间比多进程之间更容易共享数据,也因为线程一般都比进程xxx。

虚拟存储器是一个抽象概念,它为每个进程提供了一个假象,好像每个进程都在独占地使用主存。每个进程看到的存储器都是一致的,称之为虚拟地址空间。
Linux中,每个进程看到的虚拟地址空间由大量准确定义的区(area)构成,每个区都有专门的功能。
程序代码和数据。代码是从同一固定地址开始,紧接着的是和C全局变量相对应的数据区。代码和数据区是由可执行目标文件直接初始化的。
堆。代码和数据区后紧随着的是运行时堆。代码和数据区是在进程一旦开始运行时就被指定了大小的,与此不同,作为调用像malloc和free这样的C标准库函数的结果,堆可以在运行时动态地扩展和收缩。
共享库。在地址空间的中间附近是一块用来存放像C标准库和数学库这样共享库的代码和数据的区域。
栈。位域用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次调用一个函数时,栈就会增长。每次我们从函数返回时,栈就会收缩。
内核虚拟存储器。内核是操作系统总是驻留在存储器中的部分。地址空间顶部的四分之一部分是为内核预留的。应用程序不允许读写这个区域的内容或者直接调用内核代码定义的函数。
虚拟存储器的运作需要硬件和操作系统软件间的静谧复杂的互相合作,包括对处理器生成的每个地址的硬件翻译。基本思想是把一个进程虚拟存储器的内容存储在磁盘上,然后用主存作为磁盘的高速缓存。


郑重声明:资讯 【{dy}章计算机系统漫游_铤而走险的兔子的空间_百度空间】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——