CSAPP 第一章 计算机系统漫游

前言   本书的目的是让我们了解系统执行hello程序时,系统发生了什么以及为什么这样。我们通过跟踪hello程序的生命周期来开始对系统的学习。从它被创建开始,到在系统上运行,输出简单的消息,然后终止。我们将沿着这个程序的生命周期,简要地学习一些逐步出现的关键概念、专业术语和组成部分,后面的章节将围绕这些内容展开。)

1、编译系统

.c文件hello.c编译产生可执行文件的命令 linux > gcc -o hello hello.c

这个过程虽然是通过一条命令完成的,然而实际上编译系统的处理过程却是非常复杂的,大致可以分为四个阶段,分别为预处理、 编译、 汇编、链接。

 

预处理阶段:预处理器(cpp)根据以字符#开头的命令,修改原始的C程序。比如hello.c中第1行的#include <stdio.h> 命令告诉预处理器读取系统头文件stdio.h的内容,并把它直接插人程序文本中。结果就得到了另一个C程序,通常是以.i作为文件扩展名。 

编译阶段:编译器(cc1)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序,该程序包含函数main的定义,如下所示:

main:
    subq		$8, %rsp
    movl		$.LC0, %edi
    call		puts
    movl		$0, %eax
    addq		$8, %rsp
    ret

汇编阶段:接下来,汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program) 的格式,并将结果保存在目标文件hello.o中。hello.o文件是一个二进制文件,它包含的17个字节是函数main的指令编码。如果我们在文本编辑器中打开hello.o文件,将看到一堆乱码。

链接阶段:请注意,hello程序调用了printf函数,它是每个C编译器都提供的标准C库中的一个函数。printf函数存在于一个名为printf.o的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中。链接器(Id)就负责处理这种合并。结果就得到hello文件,它是一个可执行目标文件(或者简称为可执行文件),可以被加载到内存中,由系统执行。

对于hello.c简单的程序,可以依靠编译系统生成正确有效的机器代码。但是,有一些重要的原因促使程序员必须知道编译系统是如何工作的。

a、程序优化

为了使程序运行更高效、更省存储空间,我们需要了解不同c语言转换为机器码的方式。比如,一个switch语句是否总是比一系列的if-else语句高效?一个函数调用的开销有多大?while循环比for循环更有效吗?指针引用比数组索引更有效吗?为什么将循环求和的结果放到一个本地变量中,会比将其放到一个通过引用传递过来的参数中,运行起来快很多呢?为什么我们只是简单地重新排列一下算术表达式中的括号就能让函数运行得更快?(在第3章中,我们将学习x86- 64,最近几代Linux、Macintosh 和Windows计算机的机器语言。我们学习编译器是怎样把不同的C语言结构翻译成这种机器语言。在第5章中,学习如何通过简单转换C语言代码,帮助编译器更好地完成工作,从而调整C程序的性能。在第6章中,将学习存储器系统的层次结构特性,C语言编译器如何将数组存放在内存中,以及C程序又是如何能够利用这些知识从而更高效地运行。)

b、理解链接出现错误(在第7章将会学习)

比如,链接器报告说它无法解析一个引用,这是什么意思?静态变量和全局变量的区别是什么?如果你在不同的C文件中定义了名字相同的两个全局变量会发生什么?静态库和动态库的区别是什么?我们在命令行上排列库的顺序有什么影响?最严重的是,为什么有些链接错误直到运行时才会出现?

c、避免安全漏洞

缓冲区溢出错误是造成大多数网络和Internet服务器上安安全漏洞的主要原因。学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式会引起的后果。作为学习汇编语言的一部分,我们将在第3章中学习堆栈原理和缓冲区溢出错误。

2、硬件系统组成

总线:贯穿整个系统的电子管道,携带信息字节并负责在各个部件间传递。通常总线被设计成传送定长的字节块,也就是字(word)。字中的字节数(即字长)是一个基本的系统参数,各个系统中都不尽相同。现在的大多数机器字长要么是4个字节(32位),要么是8个字节(64位)。本书中,我们不对字长做任何固定的假设。

I/O(输入/输出)设备:是系统与外部世界的联系通道。示例系统包括四个I/O设备:作为用户输人的键盘和鼠标,作为用户输出的显示器,以及用于长期存储数据和程序的磁盘驱动器(简单地说就是磁盘)。最开始,可执行程序hello就存放在磁盘上。每个I/O设备都通过一个控制器或适配器与1/O总线相连。控制器和适配器之间的区别主要在于它们的封装方式。控制器是I/O设备本身或者系统的主印制电路板(通常称作主板)上的芯片组。而适配器则是一块插在主板插槽上的卡。无论如何,它们的功能都是在I/O总线和I/O设备之间传递信息。

主存:是一个临时存储设备,在处理器执行程序时,用来存放程序程序处理的数据。从物理上来说,主存是由一组动态随机存取存储器(DRAM)芯片组成的。从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯一的地址(数组索引),这些地址是从零开始的。一般来说,组成程序的每条机器指令都由不同数量的字节构成。与C程序变量相对应的数据项的大小是根据类型变化的。比如,在运行Linux的x86-64机器上,short类型的数据需要2个字节,int和float类型需要4个字节,而long和double类型需要8个字节。(第6章将具体介绍存储器技术,比如DRAM芯片是如何工作的,它们又是如何组合起来构成主存的。)

处理器:中央处理单元(CPU),简称处理器,是解释(或执行)存储在主存中指令的引擎。处理器的核心是一个大小为一个字的存储设备(或寄存器),称为程序计数器(PC)。在任何时刻,PC都指向主存中的某条机器语言指令(即含有该条指令的地址)。从系统通电开始,直到系统断电,处理器一直在不断地执行程序计数器指向的指令,再更新程序计数器,使其指向下一条指令。处理器看上去是按照一个非常简单的指令执行:模型来操作的,这个模型是由指令集架构决定的。在这个模型中,指令按照严格的顺序执行,而执行一条指令包含执行一系列的步骤。处理器从程序计数器指向的内存处读取指令,解释指令中的位,执行该指令指示的简单操作,然后更新PC,使其指向下一条指令,而这条指令并不一定和在内存中刚刚执行的指令相邻(比如跳转)。

3、高速缓存

存放处理器近期可能会需要的信息。通过高速缓存,系统可以获得一个很大的存储器,同时访问速度也很快,原因是利用了高速缓存的局部性原理,即程序具有访问局部区域里的数据和代码的趋势。通过让高速缓存里存放可能经常访问的数据,大部分的内存操作都能在快速的高速缓存中完成。

存储结构金字塔

 存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。因此,寄存器文件就是L1的高速缓存,L1是L2的高速缓存,L2是L3的高速缓存,L3是主存的高速缓存,而主存又是磁盘的高速缓存。在某些具有分布式文件系统的网络系统中,本地磁盘就是存储在其他系统中磁盘上的数据的高速缓存。

4、操作系统管理硬件

我们写的程序不会直接访问主存、磁盘、显示器等,而是依靠操作系统提供的服务。如下图:

操作系统有两个基本功能: (1)防止硬件被失控的应用程序滥用;(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。操作系统通过几个基本的抽象概念(进程、虚拟内存和文件)来实现这两个功能。如下图:

 文件是对I/O设备的抽象表示;虚拟内存是对主存和磁盘的抽象表示;进程则是对处理器、主存和I/O设备的抽象表示。计算机系统的整个抽象如下:

5、进程与线程

同一个进程内部,有多个任务并发的需求 ---> 线程(共享空间、不共享计算)

进程是静态的:程序进入内存,分配对应资源、内存空间,同时产生一个主线程

线程是动态的:是可执行的计算单元(任务)

线程切换:需要保存上下文、保存现场

一个程序,读入内存全是0和1,从内存到CPU计算需要通过总线(如何区分一段0/1是数据还是指令,通过总线类别:控制线、数据线、地址线)

问题:是不是线程数量越多执行效率越高? 不是 线程太多,很多时间都浪费在切换线程上

问题:单核CPU多线程执行有没有意义?  有

所有的处理器配置分类:

 多核CPU与缓存的组织结构:

缓存行(一次性读取的数据块):访问某个数据,先从L1找,找不到去L2找,再去L3找,如果都没有,从内存读过来放L3、L2、L1。实际中,一般一次性按照一块数据访问,叫做缓存行,依据的是空间局部性原理。(另一个程序的局部性原理叫时间局部性原理)。缓存行不能太大也不能太小(大太,访问命中率高,但是每次读取一块到L1效率低,太小则相反),目前实际中多为64字节。

超线程:

有时称为同时多线程,是一项允许一个CPU执行多个控制流的技术。它涉及CPU某些硬件有多个备份,比如程序计数器和寄存器文件,而其他的硬件部分只有二份,比如执行浮点算术运算的单元。常规的处理器需要大约20000个时钟周期做不同线程间的转换,而超线程的处理器可以在单个周期的基础上决定要执行哪一个线程。这使得CPU能够更好地利用它的处理资源。比如,假设一个线程必须等到某些数据被装载到高速缓存中,那CPU就可以继续去执行另一个线程。举例来说,Intel Core i7处理器可以让每个核执行两个线程,所以一个4核的系统实际上可以并行地执行8个线程。

6、虚拟内存

虚拟内存是一个抽象概念,它为每个进程提供了一个假象,虚拟内存的运作需要硬件和操作系统软件之间精密复杂的交互,包括对处理器生成的每个地址的硬件翻译。基本思想是把一个进程虚拟内存的内容存储在磁盘上,然后用主存作为磁盘的高速缓存。 

程序代码和数据:对所有的进程来说,代码是从同一固定地址开始,紧接着的是和C全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初始化的。

堆:代码和数据区后紧随着的是运行时堆。代码和数据区在进程一开始运行时就被指定了大小,与此不同,当调用像malloc和free 这样的C标准库函数时,堆可以在运行时动态地扩展和收缩

共享库:大约在地址空间的中间部分是一块用来存放像C标准库和数学库这样的共享库的代码和数据的区域。

栈:位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次我们调用一个函数时,栈就会增长;从一个函数返回时,栈就会收缩。

内核虚拟内存:地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区域的内容或者直接调用内核代码定义的函数。相反,它们必须调用内核来执行这些操作。

(最后的话:本人水平有限,难有不足之处,欢迎点评,后续会继续更新CSAPP系列,同时完善相关知识点,比如进程与线程、虚拟内存等等)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《计算机系统 第三版》是一本经典的计算机系统概念教材,其中的习题是帮助读者加深对计算机系统原理的理解和应用的工具。以下是对该书的习题的回答。 在《计算机系统 第三版》的习题中,涵盖了计算机系统的多个方面,包括计算机体系结构、操作系统、存储器系统、并发控制、网络通信等。这些习题的目的是帮助读者巩固对教材内容的理解,并通过实践问题的解决来培养解决复杂问题的能力。 举例来说,其中的习题可能包括: 1. 计算机系统体系结构的习题:如理解多级存储器体系结构的原理,设计一个具有多级缓存的计算机系统,并对性能进行评估。 2. 操作系统习题:如深入理解进程管理和线程管理的概念,编写一个多线程的程序,并通过调试和性能分析优化程序。 3. 存储器系统习题:如设计一个虚拟内存系统,讨论页表大小对页面错误率的影响,以及页表的压缩和局部性原理。 4. 并发控制习题:如理解并发控制的一致性和可见性概念,讨论分布式系统中多个进程的并发访问共享资源的问题,如何保证数据一致性。 5. 网络通信习题:如深入理解网络协议的工作原理,设计一个网络协议的通信实验,并进行性能测试与分析。 通过解答这些习题,读者可以加深对计算机系统原理的理解,并且培养解决实际问题的能力。同时,通过实践习题,读者能够更好地应用所学知识,加强计算机系统的实际应用能力。 ### 回答2: "计算机系统 第三版 csapp"是由深入了解计算机系统设计与实现的大师级教材。在这本书中,习题是重要的一部分,旨在帮助读者巩固和扩展他们对所学知识的理解。下面是对该书习题的一些回答和解释。 习题的目的是让读者进一步思考和实践书中所介绍的主题。这些习题包括了各个层面的知识点,例如机器级代码、汇编语言、处理器体系结构、内存层次结构、并发控制、网络编程等等。回答这些习题需要读者对这些主题有着清晰的理解和运用能力。 在回答习题时,读者应该从书中对应的章节中找到相关的信息来辅助解答。这有助于加深对知识点的理解,并且提高问题解决的效率。另外,在解答习题时,也可以参考书中的例子和实验,这样能更好地应用所学知识。 对于习题解答的思路,首先要仔细阅读题目,并且理解问题的要求。其次,要分析问题,找出解决问题所需的关键知识和技巧。然后,运用所学知识和技巧来解答问题,并进行验证和检查。最后,总结解题过程,并且思考问题的拓展和应用。 解答习题需要耐心和毅力。有些习题可能涉及到复杂的概念和技术,需要更多的时间和努力来理解和解答。但通过习题的实践和思考,读者可以更加深入地理解计算机系统的运作原理,提高解决问题的能力。 总之,“计算机系统 第三版 csapp”的习题是深入学习计算机系统设计与实现的重要途径,通过回答习题可以加深对知识点的理解,并提高自己解决问题的能力。在解答习题时,读者需要仔细阅读题目,理解问题的要求,分析问题,并运用所学知识和技巧来解答。通过实践和思考,读者可以更好地理解计算机系统,并提高自己的技术水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值