• 【读书笔记】深入理解计算机系统:第一章——计算机系统漫游


    计算机系统漫游

    信息就是位+上下文

    计算机上的所有程序和数据都是由一个一个位(即比特,bit)构成。而每个比特只有0与1两种状态,一般8个位被组成一组,称为字节(即byte)。
    系统中的所有信息——包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的,而区分这些数据对象的唯一方法是我们读到这些数据对象的上下文。
    例如,在不同上下文中,一个同样的字节序列可能表示为一个整数、浮点数、字符串或者机器指令。
    作为一名程序员,我们不应满足于表面的数据,而应该深入底层,真正了解数据在机器上的表示方法 。例如:整数和浮点数在实际上在机器上的表达方式与我们的经验其实是不同的,它们是对真值的有限近似值。有时候会有意想不到的行为表现。

    编译系统初识

    一个程序能从可以被人理解的高级程序设计语言(例如C语言)到机器语言,是由于编译系统的作用。
    以gcc为例,编译系统(compilation system)由预处理器(cpp)、编译器(ccl)、汇编器(as)和链接器(id)构成。

    预处理阶段

    预处理器根据以字符#开头的命令,修改原始的C程序,把预处理指令经过处理插入程序文本中,得到的另一个C程序以.i作为后缀。

    编译阶段

    编译器将C程序文本文件翻译成为汇编语言程序文本文件,以.s作为后缀。
    汇编语言是非常有用的,因为它为不同高级语言的不同编译器提供了通用的输出语言。(例如:C编译器和Fortran编译器残剩的输出文件都是一样的汇编语言)

    汇编阶段

    接下来,汇编器将.s翻译成为机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件.o格式的文件中。
    .o格式的文件为二进制文件。

    链接阶段

    如果程序使用了库函数,例如printf,那么链接器将把已经处理好的printf.o合并到现有文件中。
    最终的到了一个可执行目标文件。

    对于新手来说,不了解编译系统并不会影响到我们的编程,但是,了解编译系统对我们在实际编程是有很大帮助的,具体如下。

    1.了解程序的底层表示,能够在一定方面帮助我们选择更好的编程方法。

    2.理解链接时发生的错误,编写大型程序时容易出现无法解析的指令,了解编译系统能进一步了解有关全局变量和局部变量。

    3.避免安全漏洞,学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式会引起的后果。

    系统的硬件组成

    总线

    贯穿整个系统的是一组电子管道,称作总线,他携带的信息字节并负责在各个部件传递。通常总线传送定长的字节块。

    I/O设备

    I/O设备即输入输出设备是系统与外部世界的通道。常见的输入设备为鼠标、键盘,输出设备用显示器、打印机、硬盘等。每个I/O设备都通过一个控制器或适配器与I/O总线相连。

    主存(内存)

    主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说由一组动态随机存储器DRAM芯片组成。

    处理器

    简称CPU,是解释和执行存储在存储在主存中指令的引擎。处理器的核心为PC(指令寄存器),它始终指向某一条指令的地址。ALU(算术逻辑单元)用来执行一些算术与逻辑运算。

    (注:一般的书都把外存(磁盘,硬盘)单独拿出来说,本书直接把其归为I/O设备中的输出设备,也有一定道理)

    高速缓存的重要性

    根据机械原理,较大的存储设备要比较小的存储设备运行得慢,而快速设备的造价远比低速设备要高,所以主存比寄存器存储器的存取速度要慢很多。
    为了解决这一问题,系统设计者在主存中放入了高速缓存存储器,作为信息的临时集结区域,存放近期可能会需要的信息。
    高速缓存分三级,从L1到L3,存取速度递减,存储大小递增。
    大多数内存操作都能在快速的高速缓存中完成,这大大加快了系统的速度。
    而作为一个程序员,如果能意识到高速缓存的作用,能够利用高速缓存将程序的性能提高一个数量级。

    存储设备的层次结构

    根据上面提到的高速缓存思想,我们意识到不同的存储器在性能上有所差异,一般在同一个计算机中,计算机的存储设备的层次结构如下图所示。

    存储器层次结构的主要思想是上一层的存储器作为第一层存储器的高速缓存。比如说L1是L2的高速缓存。

    操作系统管理硬件

    除了一些能提高程序性能的细节,我们在编写程序时并不会接触到硬件,应用程序与硬件之间的软件我们叫做操作系统。
    操作系统有两个基本功能:

    1.防止硬件被失控的应用程序滥用;

    2.向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。

    而上面所提到的简单一致的机制即为操作系统对硬件的抽象。

    分别为:
    文件——操作系统对I/O设备的抽象表示(应该主要是指外存);
    虚拟内存——操作系统对主存和磁盘I/O设备的抽象表示;
    进程——操作系统对处理器、主存和I/O设备的抽象表示;

    进程:

    应用程序在现代操作系统中运行时,操作系统会提供一种假象,就好像系统上只有这个程序在运行。程序看上去是独占地使用处理器,主存和I/O设备。
    进程是操作系统对一个正在运行的抽象打的一种抽象。在一个系统上可以同时运行多个进程,而每个进程都好像在独占地使用硬件。而并发运行,则是说一个进程的指令和另一个进程的指令是交错执行的。CPU在多个进程中的交错执行我们称为上下文切换。
    实现进程这个抽象概念需要低级硬件和操作系统软件之间的紧密合作,进程是计算机科学中最重要和最成功的概念之一。

    线程

    在现代操作系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。

    虚拟内存

    虚拟内存是一个抽象概念,它为每个进程提供了一个假象,每个进程都在独占地使用主存。每个进程看到的内存都是一致的,称为虚拟内存空间。如下图所示(图中地址是从下往上增大的)

    下面是各个分区的简单描述:

    程序代码和数据区

    对于所有进程来说,代码是从同一固定地址开始的,紧接着的是和全局变量相对应的数据位置。

    堆区

    代码和数据区后是运行时堆,当调用malloc,free(C),new,delete(C++)时,堆可以动态地扩展和收缩。

    共享库区

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

    位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩

    内核虚拟内存

    地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区域的内容或者直接调用内核代码定义的函数。

    虚拟内存的运作是非常复杂的。基本思想是吧一个进程虚拟内存的内容存储在磁盘上,然后主存作为磁盘的高速缓存。

    文件

    文件就是字节序列,仅此而已。每个I/O设备,包括磁盘、键盘、显示器,甚至网络,都可以看成是文件。系统中的所有输入输出都是通过使用一小组称为Unix I/O的系统函数调用读写文件来实现的。
    文件这个简单而精致的概念是非常强大的,因为它想应用程序提供了一个统一的视图,来看待系统中含有的所有各式各样的I/O设备。例如处理磁盘文件内容时,程序员无须了解具体的磁盘技术。

    (这里书中简单的提到了网络,但只是大致说了一下网络传输文件的方式和方法,没什么实质的干货,遂略过,在后面具体说的时候再仔细研究)

    其他一些知识点

    Amdahl定律

    当我们对系统的某个部分加速时,其对系统整体性能的影响取决于该部分的重要性和加速程度。若系统执行某应用程序需要时间为Told。假设系统某部分所需执行时间与改时间的比例为α,而该部分性能提升比例为k。即该部分初始所需时间为αTold,现在所需时间为(αTold)/k。因此,总的执行时间为:

    Tnew=(1-α)Told+(αTold)/k=Told[(1-α)+α/k]
    由此,可以计算出加速比S=Told/Tnew为
    S=1/[(1-α)+α/k]
    Amdahl定律的主要观点——想要显著加速整个系统,必须提升全系统中相当大的部分的速度。 Amdahl定律一个有趣的特殊情况是考虑k趋向∞时的效果。这就意味着,我们可以取系统的某一部分将其加速到几乎不花费时间,于是这时:
    S=1/(1-α)

    并发与并行

    看不懂,暂略。

    计算机系统中抽象的重要性

    抽象是计算机科学中最为重要的概念之一。例如为一组函数规定一个简单的应用程序接口(API)就是一个很好的编程习惯,调用API的程序员无须了解函数是怎么实现的,只需要用这样函数来完成自己的程序即可。
    (关于抽象,有时间我会具体写一篇博客来梳理一遍计算机从硬件到软件的一层一层抽象)。

    总结

    这一章主要把本书的主要内容概述了一遍,同时也是对整个计算机系统的概述,因为我在读这本书时只有C语言和数据结构的基础,所以初次读处处碰壁,读哪哪都不懂,感觉自己是不是读这本书读的太早了,后来在知乎上看到一位网友说这本书不是让人一遍读完的,这本书是需要你在碰壁时放下书去学习,回过头来发现能看懂时继续读,直到把计算机专业的所有课程学完,这本书也就读完了。才感觉恍然大悟。
    这里要向和我一样的初学者推荐一个视频课程: [Crash Course:Computer Science]open.163.com/movie/2018/5/M/S/MDGEPAQ4K_MDGET74MS.html 这个系列视频并没有教我们编程,而是从计算机的历史入手,把计算机所有的基础专业课概述了一遍,甚至还有几乎所有计算机科学的研究方向的概述:人工智能,计算机图形学,计算机视觉等等。。十分详尽,配的动画也很有趣,是读这本书的一个好向导。
    借一位知乎网友对这本书的描述:“这是一份地图,不是一个世界”。希望能在这份地图的指引下,把计算机科学的世界完整地走一遍。

  • 相关阅读:
    133-使用django实现评论数统计功能
    132-django中的css美化(基本美化)
    java字符串处理常用方法
    SQL练习
    IntelliJ IDEA 2019.3 最新破解方法
    最详细的http协议、tcp/ip协议(转)
    B-tree和B+tree
    红黑树详解
    由一个算法题引发的哈夫曼树讲解
    sourcetree,创建工作流报错:Fatal: Not a gitflow-enabled repo yet. Please run 'git flow init' first.-》解决办法
  • 原文地址:https://www.cnblogs.com/z-y-k/p/11267543.html
Copyright © 2020-2023  润新知