文章目录
Hello World的生命周期
对源代码的编译指令
linux> gcc -o hello hell.c
编译的四大过程
- 预处理
读取文件内容,将内容插入到源程序当中
hello.c->helloi - 编译
词法分析,语法分析,语义分析,中间代码生成和优化
hello.i->hello.s - 汇编
将hello.s翻译成机器指令(二进制)
hello.s->hello.o - 链接(链接器)
将hello.o和printf.o链接
将文件与库文件相链接
可重定位目标文件(*.o)
对应于gcc编译是
- 预处理
预处理
gcc -E test.c -o test.i
编译
gcc -S test.i -o test.s
汇编
gcc -c test.s -o test.o
链接生成可执行文件
gcc test.o -o test
-E:仅作预处理,不进行编译、汇编和链接
-S:仅编译到汇编语言,不进行汇编和链接
-c:编译、汇编到目标代码(也就是计算机可识别的二进制)
-o:执行命令后文件的命名
-g:生成调试信息
-w:不生成任何警告
-Wall:生成所有的警告
运行hello.exe文件
linux>./hello
shell命令解释程序
如果第一个单词不是内置的shell命令,shell就会对这个文件进行加载并运行,shell加载并且运行hello程序
计算机系统的硬件组成
- CPU
-
PC:大小为一个字的存储区域
存放一条指令的地址,指向下一条要执行的指令
32bit 1word=4Byte
64bit 1word=8Byte -
寄存器文件:单字长的寄存器构成,每个寄存器都有自己唯一的名字,临时存放数据的空间
寄存器x,y 计算a+b
-
a:x
b:y
a+b:x/y(cover)
- ALU(算数逻辑单元):读取寄存器的内容,进行算术运算,将结果保存到寄存器,专攻算数与逻辑的计算
主存(内存):处理器在执行程序的时候,内存主要存放程序指令以及数据,主要由随机动态存储器芯片组成
可以看成从零开始的大数组,每个字节都有相应的地址
内存和处理器(CPU)之间通过总线来进行数据传递
总线:将信息从一个部件传递到另一个部件
总线被设计成传送固定长度的字节块(字)
32位机器和64位机器的传输的大小是不同的
IO输入输出设备
除了处理器内存以及总线,计算机系统包含了各种输入输出设备,例如键盘,鼠标,显示器已经磁盘等等,每个输入输出设备都通过一个控制器或者适配器与io总线相连
控制器和适配器的区别:
封装方式,无论是控制器还是适配器,他们的功能都是在IO设备和IO总线之间传递数据
‘
运行的流程:
键盘输入从UserController 读取通过io总线
shell程序将输入的字符逐一读入寄存器
处理器把hello这个字符串放入内存中
完成输入,按下程序,shell程序知道完成了命令的输入
然后执行一系列的指令来加载可执行文件hello
指令将hello中的数据和代码从磁盘复制到内存
这个复制的过程利用了DMA(Direct Memory Access)技术
数据可以不经过处理器(CPU),从磁盘直接到达内存
当可执行文件hello中的代码和数据被加载到内存中
处理器(CPU)开始执行main函数的代码
cpu将hello,world字符串从内存复制到寄存器文件
从寄存器文件复制到显示设备
三级高速缓存的引入
磁盘的容量一般为 TB 级,内存的容量一般为 GB 级,磁盘的容量大概是内存的 1000 倍。
在任务管理器可以看L1 L2 L3缓存大小
大容量的存储设置的存取速度要比小容量的慢,运行速度更快的设备的价格相对于低速设备要更贵
原因:处理器(CPU)从寄存器文件读取数据速率和内存读取速率的差异
操作系统是硬件和应用程序的中间层
为什么?
- 防止硬件被失控的应用程序滥用
- 操作系统提供统一的机制来控制这些复杂的底层硬件
操作系统提供统一的机制来控制这些复杂的底层硬件
- 文件是对IO设备的抽象
- 虚拟内存是对内存和磁盘IO的抽象
- 进程是对处理器,内存以及IO设备的抽象
- 虚拟机是对整个计算机系统的抽象,包括操作系统,处理器,以及程序
进程之间的切换
上下文:操作系统会跟踪进程运行的状态信息
当前PC和寄存器的值,以及内存中的内容
假定: shell进程和hello进程
开始:shell进程在等待命令行的输入
shell进程加载hello进程
shell进程通过系统调用来执行请求
系统调用将控制权从shell进程传递给操作系统
操作系统保存shell进程的上下文
创建hello进程和上下文
将控制权转交给新的hello进程
hello进程执行完毕
操作系统回复shell进程的上下文
将控制权交给shell进程
结束:shell进程在等待命令行的输入
通过系统调用 CPU从目态转为管态
进程由线程(Thread)组成
每个线程运行在进程的上下文中,共享代码和数据
虚拟内存
为每个进程提供假象,每个进程都在独自占用整个内存空间
第一个区域是用来存放程序的代码和数据的
这个区域的内容从可执行目标文件中加载而来
每个进程看到的内存都是一样的(虚拟地址空间)
对所有的进程来讲,代码都是从固定的地址开始
C语言中读写区域存放全局位置
堆的增长方向和栈的增长方向相反,可以在运行时动态的扩展和收缩
共享库的存放区域,主要存放c语言的标准库和数学库共享库的代码和数据。
每次程序进行函数调用的时候栈就会增长
函数执行完毕返回时,栈就会收缩
栈的增长方向从高地址到低地址
看到User Stack 的下面的箭头了嘛
地址的最顶部为内核保留的区域,应用程序不能读写这个区域的数据,这个区域对应用程序不可见
一切皆文件是什么概念:
所有的IO设备都可以看作是文件
系统所有的输入输出都可以通过读写文件来完成
Use ssh run hello program
如何使用本地计算机上的telnet客户端连接远程主机上的telnet服务器
目前ssh的方式更加普遍
在ssh客户端输入hello字符串并敲下回车
客户端的软件通过网络将字符串发送到ssh服务端
ssh服务端从网络端接收到这个字符串以后
将这个字符串传递给远程主机上的shell程序
shell程序负责hello程序的加载
运行结果返回ssh的服务端
ssh服务端通过网络将运行的结果发送给ssh的客户端
ssh客户端在屏幕上显示运行结果
任务(task):并行计算所处理的对象.
工作量 (workload):处理某任务的所需的各种开销的总和.
处理器(processor):并行计算中所使用的最基本的处理器单元.
执行率(execution rat):每个处理器单位时间能完成的工作量2.
执行时间 (execution time):处理某任务所需的时间.
加速比(scalability):当处理器个数增多时,完成某固定工作量任务所需执行时
间的减少倍数.
理想加速比(ideal scalability):处理器个数增多的比例.
并行效率(parallel efficiency):加速比:理想加速比 x100%.
系统的加速比
阿姆达尔定律Amdahl’s Law
对某一部分进行加速的时候,被加速部分的重要性和加速程度是影响整体系统性能的关键因素
K:可加速部分性能提升比例
根据公式推导,性能要提高两倍以上需要优化大部分的组件
如何获得更高的计算能力
- 线程级并发
- 指令级并行
- 单指令多数据并行
多核处理器的组织结构 look the following
每个cpu核心都有自己的L1cache, L2cache
通过增加增加CPU的核心数,可以提高系统的性能
超线程
单个cpu核心如何实现超线程
程序计数器和寄存器文件有多个备份
浮点运算部件只有一份
超线程处理器可以在单周期的基础上决定执行哪一个线程
当一个线程因为读取数据进入等待状态时
cpu可以去执行另外一个线程
线程之间的切换只需要极少的时间代价
现代处理器可以同时执行多条指令的属性成为指令级并行
被这些机制推动
多发射(multiple-issue):独立指令可同时启动;
流水线(pipelining):上文提到,算术单元可以在不同的完成阶段处理多个操作;
分支预测和推测执行(branch prediction and speculative execution):编译器可以“预测”条件指令的值是否为真,然后相应地执行这些指令;
无序执行(out-of-order execution):如果指令之间不相互依赖,并且执行效率更高,则指令可以重新排列;
预取(prefetching):数据可以在实际遇到任何需要它的指令之前被推测地请求(这将在后面进一步讨论)。
允许一条指令产生多个并行的操作单指令多数据(SIMD)
- 处理视频,声音
并行和并发
1.并行指令切换
2.并发同时执行
冯诺依曼架构
- 存储程序和数据的内存
- 一个在获取,执行,存储周期中对数据进行操作的指令处理单元
- 具有指令序列的模型也称为控制流,与数据流相对应