《深入理解计算机系统》读书笔记

第一章 计算机系统漫游

     1.程序的编译

       对于一个hello.c程序,从源文件到目标文件的转化是由编译器驱动程序(compiler driver)完成的,翻译过程分为四个阶段完成,执行这四个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统。

图1.1 编译系统

      预处理阶段。预处理器(cpp)根据以字符#开头的命令修给原始的C程序,结果得到另一个C程序,通常以.i作为文件扩展名。

       编译阶段。编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。汇编语言程序中的每条语句都以一种标准的文本格式确切地描述了一条低级机器语言指令。

       汇编阶段。汇编器(as)将hello.s翻译成机器语言指令,并把指令打包成为一种叫做可重定位目标程序的格式,并将结果保存在目标文件hello.o中。Hello.o文件是一个二进制文件,它的字节编码是机器语言指令而不是字符。

       链接阶段。此时hello程序调用了printf函数。Printf函数存在于一个名为printf.o的单独的预编译目标文件中。链接器(ld)就负责处理把这个文件并入到hello.o程序中,结果得到hello文件,一个可执行文件。最后可执行文件加载到储存器后由系统负责执行。

      2.系统的硬件组成

 

图1.2 一个典型系统的硬件组成

       总线

       贯穿整个系统的一组电子管道,携带信息字节并负责在各个部件见传递。通常总线被设计成传送定长的字节块,各种系统的字节数不相同,例如Intel Pentium系统的字节长为4字节。

       I/O设备

       I/O(输入/输出)设备是系统与外界的联系通道,主要包括:键盘和鼠标,显示器以及用于长期存储数据和程序的磁盘驱动器。每一个I/O设备都是通过一个控制器与适配器与I/O设备连接起来的。控制器是主板上的芯片组,而适配器则是一块插在主板插槽上的卡。

       主存

       主存是由一组DRAM(动态随机访问存储器)芯片组成的。在处理器执行程序时,它被用来存放程序和程序处理的数据。

       处理器

       中央处理单元(CPU)简称处理器,是解释存储在主存中指令的引擎。处理器的核心是程序计数器(PC)的字长大小的存储设备(或寄存器)。PC指向主存中的某条机器语言指令(内含其地址)。

       高速缓存

       之前但系统在执行hello程序时会有大量的拷贝工作,例如把代码和数据从磁盘磁盘拷贝到主存,从主存拷贝到寄存器堆,再从寄存器堆把文件拷贝到显示设备中。这些拷贝工作会减慢程序的实际工作。因此,为了加快程序运行速度,系统设计者采用了更小更快的存储设备,称为高速缓存存储器,它们被用来作为暂时的集结区域,存放处理器在不久的叫过来可能会需要的信息。

       形成层次结构的存储设备

       存储器分层结构的主要思想是一个层次上的存储器作为下一层次上的存储器的高速缓存。

 

图1.3 一个存储器层次结构的示例


作为一个计算机学生,很多基础知识都不知道或者已经不记得了


2.进程的虚拟地址空间
《深入理解计算机系统》读书笔记鈥斺數1,2章

第二章 信息的表示和处理
这章主要讲二进制的数据表示方式,学了4年的计算机,经常出现这些知识,但是还是有经常弄不清楚的知识
1.大端和小端存储
小端存储:
机器在存储器中按照最低有效字节到最高有效字节的顺序存储对象,也就是说最低有效字节在前面,Intel的机器就是这样
大端存储:
机器按照最高有效字节到最低有效字节的顺序存储对象,例如IBM,Sun Microsystems的大多数机器

而IBM的个人计算机使用的是与Intel兼容的处理器,许多微处理器,包括Alpha和Motorolad的PowerPC可以运行在任意存储方式中。

例如:变量x存储与0x100处,int型数值为0x01234567
《深入理解计算机系统》读书笔记鈥斺數1,2章

第二章 信息的处理和表示

       这章前面的知识其实以前也学过了些,但这章书介绍的很多细节都是以前没注意的。

       在C#中有三种最重要的数字编码。无符号编码是基于传统的二进制表示法的,表示大于或者等于零的数字。二进制补码编码是表示有符号整数的最常见的方式。浮点数编码是表示实数的科学计数法的以二为基数的版本。计算机的表示法用有限的位数来对一个数字编码,因此,当结果太大以致不能表示时,某些运算就会溢出。例如:当计算机计算表达式200*300*400*500会得出-884901888这个违背整数运算属性的结果。

       另外浮点运算与其他两种运算相比有完全不同的数学属性。虽然溢出会产生特殊的值+∞,但是一组正数的乘积总是正的。另一方面由于表示的精度有限,浮点运算是不可结合的。例如,在大多数机器上,C表达式(3.14+1e20)-1e20求得值会是0.0,而3.14+(1e20-1e20)求得的值会是3.14.

       1.信息存储

       大多数计算机使用8位的块来作为最小的可寻址的存储器单位,而不是访问访问存储器中单独的位。存储器的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能地址的集合就称为虚拟地址空间。编译器和运行是系统的一个任务就是将这个存储器空间划分为更可管理的单元,来存放不同的程序对象,也就是程序数据、指令和控制信息,然后有各种机制可以用来分配和管理程序不同部分的存储,这种管理其实完全是在虚拟地址空间里完成的。

       1.1十六进制表示法

       由于十进制和二进制表示法对于描述为模式来说都不是非常方便,所以引进了另一种替代的方法,也就是十六进制数来书写位模式。表示方法:以0x或0X开头,数字“0”~“9”和字符“A”~“F”来表示16个可能的值。取值范围:0016~FF16

       编写计算级程序的一个常见任务就是手工地在位模式的十进制、二进制和十六进制表示之间转换。二进制和十六进制之间的转换是简单直接的。例如,假设有一个数字0x173A4C,可以通过展开每个十六进制数字,将它转换位二进制格式,如下所示:

 

      这样就给出了二进制表示000101110011101001001100。

       反过来如果给定一个二进制数字000101110011101001001100,则可以通过首先将它分割为每四位一组来把它转换为十六进制,当位总数不是四的倍数,最左边的一组可以少于四位,前面用零补足。如下所示:

 

       十进制和十六进制表示之间的转换需要使用乘法或者除法来处理一般情况。将一个十进制数字转换为十六进制,可以反复地用16除x,得到一个商q和一个余数r,然后用十六进制数字表示的r作为最低位数字,并且通过q反复进行这个过程得到剩下的数字。例如,考虑十进制314156的转换:

 

      从这里可以读出十六进制表示为0x4CB2C。

      当值x是2的幂时也就是对于某个n,x=2∧n,可以很容易地将x写成十六进制形式,只要知道x的二进制表示就是1后面跟n个零。十六进制数字0代表四个二进制0.所以对于被写成i+4j形式的n来说,其中0≤i≥3,可以把x写成开头的十六进制数字为1(i=0)、2(i=1)、4(i=2)或者8(i=3),然后跟着j个十六进制的0。比如,x=2048=211,有n=11=3+4*2,从而得到十六进制表示0x800。

       反过来将一个十六进制数字表示为十进制数字,可以用相应的16的幂乘以每个十六进制数字。比如,给定数字0x7AF,计算它对应的十进制值为7*162+10*16+15=1967。

第一章 计算机系统漫游

1.信息就是位+上下文
源程序(0、1位序列;8位一组称为字节)–每个字节表示程序中某个文本字符
大部分的现代系统都是用ASCII标准来表示文本字符,这种方式实际上就是用一个 唯一的单字节大小的整数值来表示每个字符
每个文本行都以一个不可见的换行符’\n’来结束的,对应的整数值为10
系统中所有的信息——包括磁盘文件、存储器重的程序、存储器中存放的用户数据以及网络上传送的数据,都是由一串位表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。

2.程序被其他程序翻译成不同的格式
例如,gcc编译器驱动程序的翻译过程可以分为4个过程:
-hello.c源程序(文本)–> 预处理器(cpp)-hello.i被修改的源程序(文本)–> 编译器(ccl)-hello.s汇编程序(文本)–> 汇编器(as)-hello.o可重定位目标程序(二进制)+外部printf.o–> 链接器(ld)-hello可执行目标程序(二进制)–>
汇编语言非常有用,它为不同高级语言的不同编译器提供了 通用的输出语言。

3.了解编译系统如何工作是大有益处的
4.处理器读并解释存储在存储器中的指令
外壳(shell)是一个命令行解释器,输出一个提示符,等待你输入一个命令,然后执行这个命令。
通常总线被设计成传送定长的字节快,就是字(word)。
每个IO设备都通过一个 控制器适配器与IO总线相连。控制器和适配器之间的区别主要在于它们的封装方式。控制器是置于IO设备本身的或者系统的主印制电路板(主板)上的芯片组,而适配器则是一块插在主板插槽上的卡。
主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说,主存是一组动态随机存储器(DRAM)芯片组成的;从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯一的地址(即数组索引),这些地址是从零开始的。
中央处理单元(CPU),简称处理器,是解释在主存中指令的引擎。处理器的核心是一个字长的存储设备(或寄存器),成为程序计数器(PC)。在任何时刻,PC都指向贮存中的某条机器语言指令(即含有该条指令的地址)。
CPU在指令的要求下可能会执行以下操作:
加载:把一个字节或者一个字从主存复制到寄存器,以覆盖寄存器原来的内容
存储:把一个字节或者一个字复制到主存的某个位置,以覆盖这个位置上原来的内容
操作:把两个寄存器的内容复制到ALU,ALU对这两个字做算数操作,并将结果存放到一个寄存器中,以覆盖该寄存器原来的内容
跳转:从指令本身中抽取一个字,并将这个字复制到PC中,以覆盖PC中原来的值
Q:寄存器多大?
一个典型的寄存器文件只存储几百字节的信息,而主存里可以存放几十亿字节。然而,处理器从寄存器文件中读数据比从主存中读取几乎快100倍,差距还在持续增大。

5.高速缓存至关重要
L1、L2高速缓存用一种叫做静态随机访问存储器(SRAM)的硬件技术实现。利用了局部性原理,即程序具有访问局部区域里的数据和代码的趋势。

6.存储设备形成层次结构

7.操作系统管理硬件
(1)进程–是操作系统对一个正在运行的程序的一种抽象。在一个系统上可以同时运行多个进程,而每个进程都好像在独占地使用硬件。而并发运行,则是说一个进程的指令和另一个进程的指令是交错执行的。无论是在单核还是多核系统中,一个CPU看上去都像是在并发地执行多个程序,这是通过处理器在进程间切换来实现的。OS实现这种交错执行的机制成为 上下文切换
(2)线程–尽管通常我们认为一个进程只有单一的控制流,但是在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。
由于网络服务器对并行处理的需求,线程称为越来越重要的编程模型,因为多线程之间比多进程之间更容易共享数据,也因为线程一般来说都比进程更高效。当有多处理器可用的时候,多线程也是一种使程序可以更快运行的方法。
多处理器VS多核。一个cpu上多个核心,多处理器多个cpu。
(3)虚拟存储器–抽象概念,为每个进程提供了一个假象,即每个进程都在独占地使用主存。每个进程看到的是一致的存储器,称为虚拟地址空间。
地址从低到高:
程序代码和数据
共享库
内核虚拟存储器
(4)文件–字节序列。每个IO设备,包括磁盘、键盘、显示器、甚至网络,都可以视为文件。

8.系统之间利用网络通信

9.重要主题
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值