信息的表示
信息就是位+上下文,系统中的所有信息,包括c盘文件,程序,储存器中数据以及网络传输的数据,都是一串位表示的.分辨不同数据对象的惟一方式就是判定其上下文.
例如11011101这串二补码,可以表示221,在java的class文件里可能就代表一个JVM指令.
程序的编译
一个简单的C语言程序来说,通常要经过预处理器、编译器、汇编器和链接器的处理,能够被翻译成一段可执行的二补码文件。比如一段c语言helloworld程序.
程序的运行
hello.c早已被编译成可执行文件hello.假如在Unix系统中运行,须要一个叫sheel(壳体)的命令行类库加载运行.
unix> ./hello
hello, world
unix>
我们首先须要了解系统的硬件.
总线:贯串整个系统的是一组电子管线linux内核源代码漫游,也就是总线。总线传送的是字,字中的字节数字长与系统相关,例如在32位操作系统当中,一个字是4个字节,而在64位则是8个字节。
I/O设备:I/O设备是系统与外部联系的通道.I/O设备(鼠标、鼠标、显示器等)由控制器(USB控制器)或则适配器(图形适配器)与I/O总线相连,二者的区别在于一个是显卡上的芯片组,一个是显卡插孔上的卡。
寻址:它是计算机中的一个临时储存设备,在处理器执行程序的时侯,寻址就是临时储存数据的地方。化学上来说,它是由动态随后存取储存器芯片DRAM组成,逻辑上来说linux系统,它是一组连续的字节链表,每一个字节都有惟一的地址,地址从0开始。
处理器:中央处理单元,是解释储存在寻址手指令的引擎.处理器的核心是一个程序计数器(PC)linux内核源代码漫游,它在整个计算机运行的期间还会指向一个寻址中的一个显存地址,而地址当中则是一个计算机指令。处理器所做的,就是不停的执行程序计数器所指向的每一条指令。处理器所做的操作是围绕寻址、寄存器文件以及算术/逻辑单元(ALU)进行的,这儿面处理器做的最多的动作就是加载(从寻址将数据复制到寄存器)、存储(从寄存器将数据复制到寻址)、操作(将两个寄存器的内容复制到算术/逻辑单元进行操作,结果会再度复制到寄存器)以及跳转(改变程序计数器当中的内容)。
处理器当中提及的是指令集结构,不过实际当手指令集的实现是十分复杂的,那么做的目的是为了加速CPU的运算速率。我们可以这样去分辨指令集机构以及微体系结构,指令集结构是指令集的具象描述,而微体系结构则是这个具象描述的某一个具体实现,类似于JAVA虚拟机与JAVA虚拟机实现的关系。
扫描:当我们在鼠标输入./hello时,linux的壳体程序(也就是命令行)会扫描我们输入的字符,将这种字符读入到寄存器当中,之后再装入寻址。换句话说,./hello这几个字符是经过了CPU中的寄存器因而抵达了寻址。
加载:好了壳体程序晓得我们要执行hello这个程序了,开始加载,此过程会借助一种称作储存器存取的技术,致使数据不通过寄存器直接抵达寻址
运行并输出:代码以及程序所须要的数据加载到寻址后,CPU就开始从main函数的起始位置,依次执行程序中的机器语言指令。这种指令将"hello,world"这个字符串依次加载到寄存器,然后传输到显示器终端显示.
高速缓存
系统在数据的传输上耗费了大量的时间。硬件开发商为了降低这些数据传输的时间成本,采用一种高速缓存的技术去降低这些时间成本.
坐落处理器芯片上的L1高速缓存速率和寄存器几乎一样,容量更大的L2告诉缓存则通过一条特殊总线联接到处理器,速率慢一些,但仍比寻址快.它们采用静态随机访问储存器(SRAM)实现,有些系统甚至有L3告诉缓存.
设备层次
每一层上的储存器都可以作为低一层储存器的高速缓存.
进程与线程
进程是操作系统对一个正在运行的程序的具象。并发运行,指的是进程交错执行.操作系统会记录每一个进程的状态,这种状态就叫做进程的上下文。这种状态主要包括了PC,寄存器以及寻址的当前内容。当操作系统在进程间切换的时侯,也会切换相应的上下文,因而保证进程恢复到之前的状态.
现代系统中,一个进程可以由多个称为线程的执行单元组成,线程运行在进程的上下文,共享相同的代码和数据.因为共享数据更容易,所以线程更高效.
虚拟储存器
虚拟储存器是一种具象概念,为每位进程提供了一个表象,即每位进程见到的都是一致的储存器.从数学上讲,它包含了I/O设备以及寻址。在逻辑上讲,虚拟储存器被描述为虚拟地址空间.
这儿的地址自下向下依次减小,可以看出,图中标明了起始地址,分别为0x08048000(32位)以及0x00400000(64位),之后向下分别是只读代码和数据、读写数据、运行时堆、共享库的显存映射区间、用户栈以及内核虚拟显存区域.
程序代码和数据:这种内容的起始地址就是0x08048000,首先是代码,之后是一些全局变量。
堆:是运行时可以动态扩充的一部份显存区域,它可以由malloc和free这样的标准库函数操作。
共享库:用于储存共享库的代码和数据。
栈:在用户虚拟地址空间的底部是栈,这部份区域与函数的执行有密切的关系。
内核虚拟储存区域:内核是操作系统的一部份,内核也可以看做是一个进程,它在计算机运行期间总是在运行着,因而这部份显存区域对用户程序是不可见的,浅显的说就是不能用。
文件
文件是I/O设备逻辑上的概念,它似乎就是字节序列,也就是1和0组成的一些信息。为此所有的I/O设备,包括c盘、键盘、鼠标、显示器都可以看成是文件.系统中所有输入输出都是通过UnixI/O的系统函数调用读写文件实现.
网路
所有的I/O设备虽然都是文件这一具象概念的具体表现,这么网路虽然也是文件的一种,由于说究竟,它也可以被看做是一系列的字节序列。网路适配器的作用就是给计算机输入一堆被传送过来的字节序列,这儿面可能包括图片、文字,甚至可能是代码等等.
并发与并行
书中的解释是并发是指一个同时具有多个活动的系统,而并行则是指的用并发促使一个系统运行的更快.实际上浅显来讲,在单cpu,并发是一种切换来切换去执行任务过程,而倘若有多cpu,并行是真正可以同时执行不同任务的.
我们根据系统层次结构由高到低指出三个层次.
线程级并发:
在进程的具象概念下引入了线程,而线程级并发的概念,就是指的多个线程在同一时间(并非是绝对同时的)活动。
操作系统从单处理器,直至现今多核多处理器系统,乃至超线程技术,早已经历了很大的变化。这也促使针对多线程编程显得更加重要,否则就难以借助多处理器带来的益处。
针对多处理器系统来说,比较好理解,或许就是化学中将多个CPU集中在一个集成电路的芯片上。而对于超线程技术来说,则是借助N个化学内核,模拟出2N个逻辑内核的技术。在硬件上来讲,超线程须要CPU的个别部份有多个备份,例如寄存器和程序计数器,并且其它部份只有一份,例如ALU.指令级并发
指令级并行的解释是,假如处理器可以同时执行多条指令,则称这些属性为指令级并行。虽然指令级并行就是借助了指令的执行过程中会有不同的阶段linux公社,或则更精确的说,是在同一时间只会借助部份CPU的硬件,因而可以借助这一点做到多个指令并行执行。
更好的情况下,现代的好多处理器才能做到执行一条指令的平均时间仍旧不到一个周期,这些处理器就称为超标量处理器。单指令,多数据并行
单指令、多数据的概念是指一条指令可以形成多个并行执行的操作的方法。现今的一些处理器中配备了特殊的硬件,可以达到这个疗效。因为形成了多个并行执行的操作,因而都会涉及到多个数据,浅显的讲也可以理解为,一条指令操作多个数据。例如书中所提及的反例,一些处理器具有并行地对4对单精度浮点数做减法的指令.
层次结构从高到低,从并发到并行,区别应当很显著了.
具象
具象的重要性就不须要再指出了,它在计算机科学领域有着不言而喻的地位。具象可以促使一些具体的实现变的愈发便于描述,但是也可以针对一些实现的方法做出规定.
计算机系统提供的一些具象.
10
思索几个问题
先上一幅图再说,假定我们要对一些数字做相乘运算,其实我们须要一个加法器,图中选定了全加器:
11
这幅图和上面书上的图类似,并且多添加了几点,须要考虑的地方
加电自检:首先操作系统是如何运行上去的,通电时首先进行自检,通过post程序检测有没有那里坏了,完了芯片bios上的rom写入到显存的特定区域,完了再另外一个单独区域(KernalSpace)加载内核系统,能够开始运作.
中断:我们想要通过鼠标输入,这么系统如何晓得我们敲的是鼠标呢?莫非每时每刻保持监视鼠标么?虽然是我们敲鼠标时侯会给出一个中断,讯号到北桥后,内部会集成一个可编程中断控制器,得悉作出行为的是鼠标.之后再到南桥,控制器等等...
二补码?:为何计算机要用二补码?假定我们用八补码,这么我们或许须要八根线.由于元元件是通过电流来标示自身,这么可以设计类似1v,2v,..8v分别代表八补码的1,2..8.而且假如是小数怎样办?一个高精度小数,用电流来标示非常困难.而二补码异常简单,有电和没电能够标示1和0.
加法器:图上我们画的是全加器,它会由两个输入数字,一个输出和,一个输入高位,一个输出低位(注意这儿的一根线可不代表实际上的一根线,一个数字用二补码表示意味着可能会须要多根线).看起来很不错,而且假如我们不仅输入数字须要线以外,输入指令也须要线.那如何样一根线能够又输入数据又可以输入指令呢.可以用线路复用,添加一个控制位,标示输入类型.
寄存器:要处理连续的运算,上面得出的结果要重新作为被加数,而旁边的电流由于新数字的输入不断变化,这么后面的数存到那里去?寄存器应运而生.
缓存:须要了解高度缓存出现的理由,cpu运算速率太快,而寻址运算速率太慢,时间都被浪费了,才须要高速缓存.而之所以高速缓存有存在价值,在于程序局部性原理.这和是很类似的嘛...
12
多任务:初期的系统是所谓单道批处理系统,也就是一次执行一个作业,之后一个接着一个直至完成.后来有了所谓多道批处理,也就是多任务了.这么考虑一个问题,不同的作业之间可能须要的显存也不一样,如何分配呢,分配的话每次访问的地址如何办,把上面的显存空间地址加进来?我们在对cpu进行时间切块的同时也会对显存进行切块(slice),地址则会重新编撰各自内部的地址,如图中都是从101开始...
虚拟显存地址:上面说过,虚拟储存空间为让每位进程都听到一致的储存空间.试想一个问题,编程时侯每位程序须要显存空间,但每台机器的各自不同,那如何统一呢?为每台机器的显存容量分别编一个?这就用到虚拟显存地址了,32位的机器不管实际显存是多少,默认就是4g,64位同样.
系统层次:上面提过储存器层次,这么如今会有系统层次,顶部自然是一堆硬件,其次我们须要内核(系统)对硬件进行管理,完了就是程序,程序可以对内核进行直接操作,称为系统调用并且这些程序编码非常复杂.而库则是进一层的封装,所以有更多的程序是调用库进行编撰的.另外一个须要提的是,系统如何晓得用户对那个程序进行了操作?这时侯须要shell这些程序了,shell分为图形化(GUI)与命令行模式(CLI).
兼容性:似乎对于兼容的库开发的程序在不同平台上也能运行,只要库一样.而假如程序是直接调用系统内核的,这么在不同系统因为硬件可能不兼容的问题,这么显然就无法运行了.这在另一方面也就是API(ApplicationProgrammingInterface)和ABI(ApplicationBinaryInterface)比较大的区别,后者是定义了源代码和库之间的插口,前者则是描述了应用程序(或则其他类型)和内核之间的低级插口.