首页 > 代码库 > C的基础 0.引言

C的基础 0.引言

本来只是想对写c++和基于c++的数据结构的文章,但是,后来发现,对于c++中一些细节还是得要从C中以及计算机系统的细节结构进行仔细地研究,要想提高程序的效率也必须深刻地了解C,所以我这里在C的基础中选取一些重要的C以及计算机系统的内容进行总结,取书中重要的部分,不要对细节过分纠结。


C的起源:

C语言是贝尔实验室Dennis Ritchie于1969年-1973年间创建。美国国家标准学会ANSI 在1989年颁布 ANSI C的标准,并定义了C语言和一系列函数库,即“C标准库”。

C语言与UNIX操作系统关系密切,C语言一开是就是作为一种用于Unix系统的程序设计语言而开放出来的。Unix几乎全部是由C编写的。C语言小而简单。


计算机系统的硬件组成:

总线:贯穿整个系统的一组电子管道。负责在个部件间传递信息,总线传递的字节块称之为字,而字长为一个重要的系统参数,现在普遍为64位。

I/O设备,与外界连接的通信通道,显示器,键盘,鼠标 , 磁盘之类。磁盘是IO设备。IO通过 控制器或者适配器 与IO总线相连

主存,是一个临时的储存设备,一般为 动态随机存取存储器DRAM组成,用来存放程序和程序处理的数据。

处理器:中央处理器CPU,是执行储存在主存中指令的引擎。处理器的核心是一个字长的寄存器,称为 程序计数器PC,在任何时刻PC都指向主存中某条指令的地址。处理器则不断的处理储存在PC中地址指向的指令。

CPU执行指令按照一个指令集进行指令的执行,而一条指令的执行是一系列的步骤:从PC中读取指令,解释指令的位,执行指令指示的简单操作,更新PC使其指向下一条指令。操作都是围绕着主存,寄存器和 算术/逻辑单元ALU进行的。

CPU指向指令的要求的操作有:

加载,将一个字或者字节从主存复制到寄存器

存储,将一个字或者字节从寄存器复制到主存中

操作,将两个寄存器中的内容复制到ALU中,进行算术操作,并将结果存放到一个寄存器中。

跳转。从指令本身抽取一个字,并将这个字复制到PC上。


高速缓存以及存储器的层次结构:

系统加载程序时,程序由磁盘上复制到主存上,运行时,指令又从主存上被复制到处理器上。在这种结构中,主存为磁盘的高速缓存,寄存器为主存的高速缓存。

由于处理器在不同的储存器中的访问速度不同,则为了提高系统的效率,则有了高速缓存以及储存器层次结构。存储器的层次结构的主要思想是一层上的存储器作为低一层存储器的高速缓存

一般有三种高速缓存L1,L2,L3 高速缓存,都为SRAM,静态随机访问存储器,CPU对SRAM的读取速度比DRAM要快。然后CPU读取速度最快的是CPU上的寄存器,但是由于造价贵,所以较高层的容量较小。然后是L1,L2,L3,主存,磁盘,远程储存(分布式文件系统,Web服务器)。层次越高,速度更快,但价格更高,容量也较小,层次越低,则相反。


应用程序一般无法直接访问IO设备和主存,而是通过操作系统提供的服务进行访问的。

操作系统是应用程序和计算机底层之间的一个程序。操作系统的基本功能:

防止硬件被失控的应用程序滥用,向应用程序提供简单一致的机制来控制复杂而又大相径庭的低级硬件设备。操作系统通过几个抽象的概念来实现这两个功能,进程,虚拟存储器,和文件。


进程:

是一个正在运行的程序的一种抽象。一个系统中可以同时运行多个进程,每个进程都好像在独占硬件。多个进程 并发运行,其实是指一个进程的指令与其他进程的指令 交错执行,但是由于CPU运算速度较快,使得CPU看起来在同时并发的执行多个进程。操作系统实现的交错执行的机制 称为  上下文切换。 操作系统保持跟踪进程运行所需的所有状态信息,称为上下文,其中包含如PC,寄存器的当前值以及主存中的内容等信息。

线程:

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

虚拟存储器:

为每一个进程提供一个假象,即每个进程都在独占的使用主存。每个进程的虚拟空间地址由大量的准确定义的区构成,每个区都有专门的功能。地址较小的端称之为低地址位,地址较大的位称之为高地址位,按照低地址到高地址的顺序有:

程序代码和数据:对于所有进程,代码都是从同一固定地址开始的,在32位系统中为0x08048000,64位系统为0x00400000。紧接着是C中全局变量所对应的数据位置。

堆:代码和数据区后紧随着的是运行时堆。代码和数据区是进行时一开始就被规定了大小。而当使用malloc和free这些C标准库中的函数时,堆运行扩展和收缩。

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

栈:位于用户虚拟地址控件顶部的是用户栈,编译器用它来实现函数调用。和堆一样,栈也可以在进程执行期间进行动态的扩展和收缩。当我们调用一个函数时,栈会增长,当一个函数返回时,栈会收缩。所有的非全局变量都保存在栈中,因为局部变量都保存在函数中,而只有当函数调用时,才会跟随函数出现在栈中。

内核虚拟存储器:内核总是驻留在内存中,是操作系统的一部分。不允许程序进行操作。

这里的堆和栈与数据结构中的堆和栈不同,数据结构中的栈是一种先入后出的储存结构,而堆是一棵包含n个节点的完全二叉树。

虚拟存储器的基本思想是将一个进程虚拟存储器的内容储存在磁盘上,使用主存作为磁盘的高速缓存,而让进程以为进程的所有内容已经复制到主存上了。这样极大的节约了主存的空间。


文件

文件是一个字节序列。每个IO设备,包括磁盘,键盘,显示器,甚至网络,都可以视为文件。系统所有的输入输出都是通过使用系统函数调用读写文件来实现的。


并发与并行:并发是指一个同时具有多个活动的系统。并行是指用并发是系统运行的更快。

超线程:同时多线程,允许一个CPU同时执行多个控制流的技术。其实也只是一个CPU并发运行多个线程,只是在硬件的一些改进,增加一些CPU硬件,使其可以保存更多数据,然后可以在一个时钟周期内就进行线程的切换,而正常的CPU需要20000个时钟周期才能进行切换。

指令级并行:使用流水线,使一个时钟周期内可以完成多个指令。一个处理器达到比一个周期一条指令更快的执行速率,称称之为超标量处理器。

单指令 多数据并行:允许一个指令产生多个可以并发执行的操作,SIMD并行。

计算机系统中的抽象:使用抽象来隐藏实际实现的复杂性。文件是对IO设备的抽象,虚拟存储器是对主存和IO的抽象,进程是对处理器和主存和IO的抽象,指令集结构是对CPU的抽象,虚拟机是对操作系统和主存和CPU和IO的整体的抽象。