深入理解计算机系统-第一章

学好计算机系统这门课,可以写出更好的代码。

话不多说,我们开始吧!

我们从这个简单的hello.c文件来看看它的生命周期。

//This is our hello.c 
#include <stdio.h>
int main()
{
    printf("Hello world,fuck u man!\n");
    return 0;
}

源程序实际上就是一个由0/1组成的位序列,8 bit一组为一个Byte。大部分计算机都采用ASCII standard来表示文本字符,给字符和二进制数码一个链接的桥梁。比如在我们的#include这一部分,#对应是35(10进制),i对应是105(10进制),etc。

像hello.c this kinda file composed of ASCII "char"被称为文本文件,所有其他文件都被称为二进制文件。

 

说了这么多,我们想说得是,系统中的所有信息,including disk files、programs in the memory or data processing via the net都是由一串比特表示。

 

彩蛋:C 语言 是贝尔实验室的Dennis Ritchie老爷子创建的,后面慢慢完善标准,大部分Unix OS内核等工具或库都是由C语言编写,电子科大有个专业也叫嵌入式系统,估计也是深入学习C\C++的。对C语言的评价,萌新不敢开腔(四川话里,开腔就是说话),C语言是系统编程的首选,它的指针写起来还是让我很难受。同时,C还缺乏对一些抽象(我们之后再说)的显式支持,比如类、对象和异常。C++andJava这种程序就解决了这种问题。

我们现在来看看这个c程序,to run this .c -file in the system,every c sentence must be converted into low-class machine-oriented language instructions。然后这些指令再按照一种可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。

GCC编译器中:

首先是hello.c源程序(文本)经过预处理器变成修改了的源程序(文本)hello.c,然后再经过编译器(ccl)变成汇编程序(文本)hello.s(高级语言转化成输出语言),再经过汇编器(as)变成可重定位的目标二进制程序hello.o(将汇编语言程序翻译成机器语言指令序列,打包成.o二进制文件),然后再引入printf.o通过链接器ld变成hello这个可执行目标二进制程序。这几个“器”一起构成了编译系统。通过这几个器的过程也被称为某某阶段。

我们再看看系统的硬件组成:

 

 

对于计算机系统,主要的硬件是总线,I/O,主存,处理器,我不写了,大学计算机基础而已。

然后再运行hello程序的时候:

(南京大学教授的ppt)

理解这样一个过程最好别用windows的系统,我们可以用ubuntu的终端来理解,I/O设备输入,经过I/O桥读入到寄存器当中,再把信息读入到内存当中。当我们敲下回车键的时候,shell就知道我们已经结束了命令的输入。然后shell执行指令加载可执行的hello文件,这些指令将hello目标文件中的代码和数据从文件所依附的磁盘复制到主存。一旦代码和数据被加载到了主存,处理器就执行机器语言指令,这样hello world这句话就到了寄存器中,再从寄存器到了I/O设备(显示器)。然后你的控制台就会显示:

Hello world,fuck u man!

提一下,我们把寄存器当成I/O设备和计算机系统交互的中介来看待,input进去先得见到寄存器,output出来也得见到它

 

接下来我们来看看高速缓存:这个例子说明了一个问题,就是系统花了很多的时间浪费在信息的转移上,从程序员的角度来看,这些duplication就是开销,减慢了程序真正的工作,因此,系统设计者一个主要目标就是加快这些复制工作。

    according to some machine-oriented theorem,较大的存储设备运转得比较小得存储设备慢,但是快速设备的造价远高于同类的低价设备。比如寄存器文件只存储几百bytes信息,主存里面可以存放几十亿bytes。但是从寄存器中读取数据比从主存中快一百倍,随着近年的semi-conductor tech进步,处理器和主存之间的差距还会继续变大。加快处理器的速度效率比加快主存的运行效率大得多。

针对这种差异,系统设计者采取了更小更快的存储设备,称为高速缓存寄存器,就是cache (or cache memory)作为暂时的集结区域来存放处理器近期可能回需要的数据。cache的容量可以很大,访问速度和寄存器文件近乎一样快。部分位于芯片上的cache利用了静态随机访问存储器SRAM硬件技术。利用cache可以将程序的性能提高一个档次,大部分内存操作都可以在快速的cache中完成。

我用ppt稍微展示一下加了cache的cpu芯片内的构造:

在后面的学习我们会更加深入的,现在先到此为止。

 

我们再来看看层次化的存储设备:

实际上,每台计算机的存储器之间都组织成了一个存储器层次结构,从上到下访问速度减慢,容量越来越大,每字节的造价也越来越便宜,如下:

 

存储器层次结构的主要思想就是把上一层的存储器作为低一层存储器的cache。

 

接下来我们再看看操作系统管理硬件:

回到hello.c程序,当shell在加载运行程序的时候,shell or hello.c都没有直接访问I/Oor存储设备而是依靠Operating system提供服务,OS可以被看成程序和硬件之间的一层软件。OS有两大基本功能,防止硬件被失控的应用程序滥用和向程序提供机制来控制低级硬件设备,通过几个基本的抽象概念来实现这两大功能,即文件,进程和虚拟内存。

我们接下来再看看进程与线程,在我前面的水文里面已经讲过了,不了解的同学可以过去看。

进程造成了计算机系统的一个假象,就是当你在运行一个程序的时候你以为整个计算机都在为你这个程序而工作,是系统内存的唯一对象。进程是对操作系统正在运行的程序的一种抽象,一个系统可以同时运行多个进程,只是由于时间片的作用看上去只是在运行一个程序。现在多核处理器已经可以实现多个程序一起跑路了。一个进程可以有多个线程组成,多线程更容易共享数据。

 

我们接下来看看虚拟内存:虚拟内存计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。(摘自百度)

每一个进程看到的虚拟地址空间都由大量准确定义的区构成,我们列举一下这些区:程序代码和数据区、堆区(比如动态开辟数组大小的malloc之类的)、共享库(math.h之类的)、栈区(实现函数调用)、内核虚拟内存。

 

再看看文件:就是字节序列。每一个I/O设备,包括网络,都可以看成文件。系统中所有输入输出都是通过使用一小组称为UnixI/O的系统函数读写文件实现的。

 

网络也是一种I/O设备,通过网络适配器链接上了I/O总线,通过网络的蕉流,系统就不只是一个孤立的硬件和软件相互交织的集合体。

Amdahl定律:对系统每一部分加速,其相对于系统整体性能的影响取决于该部分有多么重要,加速效果有多少,故此得出重要结论:想要显著加速整个系统,你需要提升全系统中相当大部分的速度。这个定律也可以用在其他方面,比如我该怎么样提高自己的均分才能更稳地保研清北?全科都得学得更好。

 

再看看并发(concurrency):一个同时具有多个活动的系统

并行(parallelism):利用并发使得系统运行的更快。具体的咱们先不管了。

 

最后咱们来看看计算机系统中抽象的重要性:

例如,为一组函数规定一个简单的应用程序接口就是一个很好的编程习惯,程序员不用了解其内部工作就可以使用这些代码,不同语言提供不同形式的抽象模式,例如C++类的声明andC的函数原型。

虚拟的想法是划时代的,比如IBM题初的虚拟机。我们第一章的学习到此为止。

 

终于可以学其他的坑了,下一个坑就是我发的算法入门。csapp先往后稍稍,笔者九月得准备竞赛了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值