源程序是由值0和1组成的位(比特)序列。
8个位是一个字节。
每个字节表示程序中的文本字符。(ASCII)
由ASCII字符构成的文件称为文本文件,其他的都成为二进制文件,如:视频文件,图片文件,mp3文件等。
ASCII码用唯一的单字节大小的整数值赖表示每个字符。2^8=256个字符。
基本思想:系统种的所有信息,包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。
区分不同数据对象的唯一方法就是读取这些数据对象时的上下文。在不同的上下文中,同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。
1969-1973:C语言-贝尔实验室
ISO定义了C语言和函数库的标准,即C标准库。
C语言成功的原因:
1.C与Unix操作系统关系密切。
2.C语言小而简单。
3.C语言是为实践目的设计的。C语言是设计用来实现Unix操作系统的。
C语言是系统级语言的首选。
Linux> gcc -o hello hello.c
Gcc编译器驱动程序读取hello.c,翻译成一个可执行目标文件hello。
翻译过程分四个阶段:分别由(预处理器cpp、编译器ccl、汇编器as、链接器ld)一起构成了编译系统。
源程序---修改后的源程序--汇编程序--可重定位目标程序--可执行程序
hello.c---hello.i ------------hello.s-------hello.o---------------hello
预处理阶段:cpp将include命令引入的头文件内容插入程序文本中。
编译阶段:ccl将C代码翻译成汇编代码。
汇编阶段:as将汇编代码翻译成机器语言指令,并打包成可重定位目标程序,保存在hello.o文件中。
链接阶段:ld将调用函数的目标文件合并到hello.o中,得到可执行文件。
可执行文件:可被加载到内存中,由系统执行。
GNU项目:有大量的工具。
程序员为什么要知道编译系统工作原理?
1.优化程序性能。
2.理解链接时出现的错误。
3.避免安全漏洞。
shell是一个命令行解释器,它输出一个提示符,等待输入的命令行,然后执行这个命令。
如果命令行第一个单词不是内置的shell命令,那么shell就会假设是一个可执行文件的名字,将加载并运行这个文件。
加载和运行的过程是怎么实现的?
系统的硬件组成:
1.总线:贯穿整个系统的一组电子管道,称为总线。它携带信息字节,并负责在各个部件间传递。
通常总线被设计成传送定长的字节块(字:word)。
word中的字节数叫字长,不同系统中代表的机器字长不同,可能是4字节32位,也可能是8字节64位
2.I/O设备:用户输入设备(鼠标和键盘),输出设备(显示器,打印机),存储设备(磁盘)。每个I/O设备都通过控制器或者适配器与I/O总线相连。
控制器和适配器区别在于封装方式。控制器是封装在设备本身或者系统主板上的芯片组,而适配器是插在主板插槽上的外置卡。功能都是在I/O总线和I/O设备之间传递信息。
3.主存:临时存储设备,由一组动态随机存取存储器(DRAM)芯片组成。逻辑上是一个线性的字节数组。每个字节都有其唯一的地址(编号或者说是数组索引),这些地址是从0开始的。
4处理器:CPU,是解释或执行存储在主存中指令的引擎。处理器的核心是一个大小为一个字的寄存器,称为程序计数器(PC)。PC在任何时刻都指向主存中的某条机器语言指令,即PC中存的是内存地址。
指令集架构---处理器的微体系结构
指令集架构:描述每条机器代码指令的效果。
微体系结构:描述的是处理器实际上是如何实现的。
指令执行:cpu从pc指向的内存处读取指令,解释指令中的位,执行该指令的简单操作。然后更新PC,指向下一条指令。
CPU指令的简单操作:
加载:从主存复制一个字节或者字到寄存器,以覆盖寄存器原来的内容。
存储:从寄存器复制一个字节或一个字到主存的某个位置,覆盖位置上原来内容。
操作:把两个寄存器的内容复制到ALU,ALU对这两个字做算术运算,并将结果存放到一个寄存器中。覆盖原来的内容。
跳转:从指令中抽取要操作的字,并将这个字复制到PC中,以覆盖PC中原来的值,这个抽取的字必定是内存地址。
直接存储器存取技术(DMA):数据可以不通过处理器直接从磁盘到主存。
shell指令执行hello程序的过程:
hello可执行文件从磁盘到内存,helloword字符串的字节从内存到寄存器,又从寄存器到显示器,显示器的GPU将字节信息翻译成字符显示到屏幕上。
高速缓存:
hello执行过程的示例展现了一个重要问题,即系统花费了大量的时间把信息从一个地方挪到另一个地方。hello程序的机器指令最初是存放在磁盘上,当程序加载时,复制到主存;处理器运行时,从主存复制到处理器;最终将要展示的内容从主存上复制到寄存器,又从寄存器复制到显示器。
高速缓存存储器(cache memory):简称为cache或高速缓存,作为暂时的集结区域。存放处理器近期可能会需要的信息。
L1高速缓存 --数万字节
L2高速缓存--数百万字节
L1,L2高速缓存是用静态随机访问存储器(SRAM)的硬件技术实现的。
系统可以利用高速缓存的局部性原理,即程序具有访问局部区域里的数据和代码的趋势。通过让高速缓存里存放可能经常访问的数据,大部分内存操作都能在快速的高速缓存中完成。
存储设备形成层次结构:
结构中:设备访问速度越来越慢,容量越来越大,造价越来越便宜。
存储器层次结构的主要思想是上一层存储器作为低一层存储器的高速缓存
寄存器
L1高速缓存
L2高速缓存
L3高速缓存
主存
本地二级存储
远程二级存储
操作系统管理硬件:
操作系统是应用程序和硬件之间插入的一层软件。所有应用程序对硬件的操作尝试都必须通过操作系统。
操作系统又两个基本功能:
1.防止硬件被失控的应用程序滥用。
2.向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
操作系统通过几个基本的抽象概念:进程、虚拟内存和文件。
文件是对I/O设备的抽象表示。
虚拟内存是对主存和磁盘I/O设备的抽象表示。
进程则是对处理器、主存、I/O设备的抽象表示。
进程是对操作系统运行程序的一种抽象。一个系统上同时可运行多个程序,每个程序都像独占计算机资源,称为并发运行。实际上多个进程的指令是交错执行的,这种交错执行的机制叫做上下文切换。
线程:一个进程中有多个线程运行在它的上下文中。共享同样的代码和数据。
虚拟内存:每个进程可看到的虚拟内存是一致的,称为虚拟地址空间。
虚拟地址空间分成多个区:
1.程序代码和数据。对所有进程来说,代码都是从同一固定地址开始。接着是和C全局变量相对应的数据位置。程序一开始运行就指定了大小。
2.堆:代码和数据区后紧随着的是运行时堆。运行时动态扩展和收缩。
3.共享库:位于地址空间中间部分。
4.栈:位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。运行期间可动态扩展和收缩。
5.内核虚拟内存:地址空间顶部区域是内核保留区。不允许应用程序读写内核内容或直接调用内核代码定义的函数。
文件:文件就是字节序列。每个I/O设备都可以看成文件。
系统之间的网络通信:
将网络看做一个I/O设备。系统可以从主存复制一串字节到网络适配器,数据流通过网络到达另一台机器。
小结:
系统不仅仅是硬件,而是硬件和系统软件互相交织的集合体。它们需要协同操作以达到运行应用程序的最终目的。
1.Amdahl定律:我们对系统的某个部分优化时,其对系统整体性能的影响取决于该部分的重要性和优化程度。想要明显加速整个系统,必须提升全系统中大部分的速度。
并发和并行:做的更多,做的更快。
并发:同时具有多个活动的系统。
并行:指用并发来使一个系统运行的更快。
1.线程级并发。多核和超线程。超线程是内核中有PC和寄存器备份。
2.指令级并行。指令流水线。如果处理器可以达到一个周期一条指令更快的执行速率,就称之为超标量处理器。
3.单指令、多数据并行。SIMD并行。主要为提高处理影像、声音、视频数据应用的执行速度。
计算机世界中抽象的重要性:
文件是对I/O设备的抽象。
虚拟内存是对程序存储器的抽象。
进程是对一个正在运行的程序的抽象。
虚拟机是对整个计算机的抽象,包括操作系统、处理器、程序。