计算机组成 -- 函数调用
程序栈123456789101112131415// function_example.c#include <stdio.h>int static add(int a, int b){ return a+b;}int main(){ int x = 5; int y = 10; int u = add(x, y);}
12$ gcc -g -c function_example.c$ objdump -d -M intel -S function_example.o
1234567891011121314151617181920212223242526272829303132333435363738......0000000000000000 <add>:......int static add(int a, int b){ 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: ...
计算机组成 -- goto
CPU执行指令
CPU是由一堆寄存器组成的,而寄存器是由多个触发器(Flip-Flop)或者锁存器(Latches)组成的简单电路
触发器和锁存器是两种不同原理的数字电路组成的逻辑门
N个触发器或者锁存器,就可以组成一个N位的寄存器,能保存N位的数据,64位的Intel服务器,寄存器就是64位的
寄存器分类
PC寄存器(Program Counter Register),也称为指令地址寄存器(Instruction Address Register)
用来存放下一条需要执行的计算机指令的内存地址
指令寄存器(Instruction Register)
用来存放当前正在执行的指令
条件码寄存器(Status Register)
用里面的一个个标志位(Flag),存放CPU进行算术或者逻辑计算的结果
其它
整数寄存器、浮点数寄存器、向量寄存器、地址寄存器、通用寄存器
程序执行
CPU会根据PC寄存器里面的地址,从内存里把需要执行的指令读取到指令寄存器里面执行
然后根据指令长度自增,开始顺序读取下一条指令,一个程序的指令,在内存里面是连续保存的,也会一条条顺序加载
特殊指令,如J类指令(跳转 ...
项目立项 -- 保证不亏钱
问题抽象一下:假设有n个坑,第$i$个坑投注了$X_i$,倍率为$Y_i$,怎样设置倍率才能保证不亏钱?
推导过程如下:
假设某场第$k$个坑赔最少,最少赔付记为$min = (X_k \times Y_k)$
则$(X_k \times Y_k) \leq (X_l \times Y_l) \quad l \in [1,n]$
易得$\frac{X_k \times Y_k}{Y_l} \leq X_l \quad l \in [1,n]$
而收入为$(\sum_{i=1}^n{X_i}) \geq (\sum_{i=1}^n{\frac{X_k \times Y_k}{Y_i}}) = (\sum_{i=1}^n{\frac{1}{Y_i}}) \times (X_k \times Y_k) = (\sum_{i=1}^n{\frac{1}{Y_i}}) \times min$
而不亏钱,只要保证$(\sum_{i=1}^n{X_i}) \geq min$即可,而由上易知,$(\sum_{i=1}^n{\frac{1 ...
计算机组成 -- 指令
CPU + 计算机指令
硬件的角度
CPU是一个超大规模集成电路,通过电路实现了加法、乘法乃至各种各样的处理逻辑
软件工程师的角度
CPU就是一个执行各种计算机指令的逻辑机器
计算机指令是一门CPU能听懂的语言,也称为机器语言
不同的CPU能够听懂的语言不太一样,两种CPU各自支持的语言,就是两组不同的计算机指令集
计算机程序平时是存储在存储器中,这种程序指令存储在存储器里面的计算机,叫作存储程序型计算机
代码 -> 机器码(编译 -> 汇编)1234567// test.cint main(){ int a = 1; int b = 2; a = a + b;}
编译(Compile)成汇编代码:把整个程序翻译成一个汇编语言(ASM,Assembly Language)的程序
汇编:针对汇编代码,用汇编器(Assembler)翻译成机器码(Machine Code)
机器码由0和1组成的机器语言表示,一串串的16进制数字,就是CPU能够真正认识的计算机指令
汇编代码 + 机器码12345678910$ gcc --help-c ...
计算机组成 -- 提升性能
CPU的功耗12CPU time = 时钟周期时间(Clock Cycle Time) × CPU时钟周期数(CPU Cycles) = 时钟周期时间(Clock Cycle Time) × 指令数 × 每条指令的平均周期数(Cycles Per Instruction,CPI)
80年代开始,CPU硬件工程师主要着力提升CPU主频,到功耗是CPU的人体极限
CPU,一般被叫做超大规模集成电路,这些电路,实际上都是一个个晶体管组合而成的
CPU计算,实际上是让晶体管里面的『开关』不断地去打开或关闭,来组合完成各种运算和功能
如果要计算得快,有两个方向:增加密度(7nm制程)、提升主频,但这两者都会增加功耗,带来耗电和散热的问题
密度 -> 晶体管数量
主频 -> 开关频率
如果功耗增加太多,会导致CPU散热跟不上,此时就需要降低电压(低压版CPU)
1功耗 ≈ 1/2 × 负载电容 × 电压的平方 × 开关频率 × 晶体管数量
并行优化 – 阿姆达尔定律1优化后的执行时间 = 受优化影响的执行时间 / 加速倍数 + 不受影响的执行时间
其它
加速大概率事件(C ...
计算机组成 -- 性能
性能指标
响应时间(Response time)、执行时间(Execution time)
执行一个程序,需要花多少时间
吞吐率(Throughput)、带宽(Bandwidth)
单位时间范围内,能处理多少数据或执行多少指令,可以通过多核、集群等方式来提升吞吐率
性能 = 1/响应时间
CPU时钟
time命令
real time
Wall Clock Time/Elapsed Time,运行程序整个过程中流逝掉的时间
user time
在用户态运行指令的时间
sys time
在操作系统内核里运行指令的时间
程序实际花费的CPU执行时间:CPU time = user time + sys time
程序实际占用的CPU time一般比Elapsed Time少(单核情况下)
123456$ time seq 1000000 | wc -l1000000real 0m0.024suser 0m0.018ssys 0m0.005s
程序实际花了0.024s,CPU time只有0.018s+0.005s=0.02 ...
计算机组成 -- First Draft
从输入设备读取输入信息,通过运算器和控制器来执行存储在存储器里的程序,最终把结果输出到输出设备中
参考资料深入浅出计算机组成原理
计算机组成 -- 知识地图
参考资料深入浅出计算机组成原理
Linux使用 -- awk
awk sed
awk更像是脚本语言
awk:用于比较规范的文本处理,用于统计数量并输出指定字段
sed:用于将不规范的文本,处理为比较规范的文本
控制流程
输入数据前例程**BEGIN{}**
主输入循环**{}**
所有文件读取完成例程**END{}**
记录和字段
每行称为AWK的记录
使用分隔符(可以自定义,默认是空格和制表符)分隔开的单词称为字段
字段的引用
$1 $2 ... $n:表示每一个字段
-F:自定义分隔符,可以使用正则表达式
1234567[root@localhost ~]# awk -F"'" '/^menu/{print $2}' /boot/grub2/grub.cfgCentOS Linux (3.10.0-1062.el7.x86_64) 7 (Core)CentOS Linux (0-rescue-6a299ef164734d338007f5e88cee6be0) 7 (Core)[root@localhost ~]# awk -F ...
Linux使用 -- sed
sed awk
sed:一般用于对文本内容做替换
awk:一般用于对文本内容进行统计、按需要的格式进行输出
替换指令模式空间
将文件以行为单位读取到内存(模式空间)
使用sed的每个脚本对该行进行操作
处理完成后输出该行
替换命令s123sed 's/old/new/' filenamesed -e 's/old/new/' -e 's/old/new/' filename ...sed -i 's/old/new/' 's/old/new/' filename ...
带正则表达式的替换命令s
12sed 's/正则表达式/new/' filenamesed -r 's/扩展正则表达式(+、?、|)/new/' filename
样例基本使用12345678910111213141516[root@localhost ~]# echo a a a > afile[root@localhost ~]# sed 's/a/aa/' afi ...