深入理解计算机系统:几个重要概念
2018-10-17 19:21
302 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/louzhangpeng/article/details/83116266
编译器(cc1):hello.i —> hello.s
汇编器(as):hello.s —> hello.o
链接器(ld):hello.o + printf.o —> hello
执行程序系统
编译系统
- 从源代码文本文件到可执行目标文件的转化由编译系统(compilation system)完成
预处理器(cpp):hello.c —> hello.i
根据以字符
#
开头的指令修改原始程序
-
将预处理之后的文本文件翻译为汇编语言程序(依然是文本文件)
-
将汇编语言程序翻译成一系列机器语言指令,然后将机器语言指令打包成可重定位目标程序
-
将程序用到的其他模块与当前程序链接到一起,最终得到可执行目标文件
程序计数器 PC
- 程序计数器为一个字长(64 位系统中是 8 个字节)的存储设备,是 CPU 的核心
- 在任何时刻,PC 都指向内存中的某条机器语言指令,也就是说,PC 中保存着一条机器语言指令的地址
- CPU 不断地执行 PC 指向的指令,然后更新 PC,使其指向下一条指令(前后指令不一定相邻)
存储器层次结构
- L0:CPU 寄存器
- L1 ~ L3:L1 ~ L3 高速缓存(SRAM,静态随机访问存储器)
- L4:主存(DRAM,动态随机访问存储器)
- L5:本地磁盘
- L6:远程存储设备(分布式文件系统、Web 服务器)
局部性原理
- 程序具有访问局部区域里的数据的趋势
操作系统抽象
进程:对处理器、主存和 I/O 设备的抽象
- 处理器在多个进程间快速切换,称为上下文切换 单处理器在任一时刻只能执行一个进程的代码
- 当操作系统把控制权从一个进程转移到另一个进程时,便进行上下文切换: 保存当前进程的上下文
- 恢复新进程的上下文
- 将控制权转移到新进程
线程
- 一个进程可以由多个线程组成,每个线程都运行在进程的上下文中,并共享相同的代码和全局数据
- 线程一般比进程高效,多线程之间共享数据也比进程之间容易
虚拟存储器:对主存和磁盘 I/O 的抽象
- 每个进程使用专有的虚拟地址空间,从而形成每个进程独占主存的假象
- 每个进程看到的虚拟地址空间由一组准确定义的区构成,从低地址到高地址依次为: 程序代码和数据
- 运行时堆
- 共享库
- 用户栈
- 内核虚拟存储器
文件:对 I/O 设备的抽象
- 文件就是字节序列,别无其他
- 每个 I/O 设备都可视为文件
- 系统的所有输入输出都通过一组 Unix I/O 系统函数调用读写文件来实现
信息存储
字
- 任一计算机的字长指明了整数和指针数据的标称大小
- 字长决定了虚拟地址空间的最大大小,对于字长为 www 的机器,其虚拟地址的范围是 0∼2w−10 \sim 2^w - 10∼2w−1
无符号数
问题代码一
- 当
length
为0
时,length - 1
转为最大的无符号数,而i
作为int
型整数,所能包含的数永远小于length - 1
- 同样,当
length
大于int
所能表示的最大数时,也会形成无限循环
float sum_elements(float a[], unsigned length) { int i; float result = 0.0; for (i = 0; i <= length - 1; i++) // 正确写法:i < length result += a[i]; return result; }
问题代码二
strlen()
返回的size_t
为无符号类型,有无符号类型参与运算的结果依然是无符号类型,因此strlen(str1) - strlen(str2)
永远不会小于0
size_t strlen(const char* str); int strlonger(const char* str1, const char* str2) { return strlen(str1) - strlen(str2) > 0; // 正确写法 return strlen(str1) > strlen(str2); }
问题代码三
- 如果
maxlen
是一个负值,len
便被赋为负值,接着再赋给memcpy
函数中的n
参数,但是参数n
是无符号值,从而转为一个很大的整数
void* memcpy(void* dest, void* src, size_t n); #define KSIZE 1024 char kbuf[KSIZE]; int copy_from_kernel(void* user_dest, int maxlen) { int len = KSIZE < maxlen ? KSIZE : maxlen; memcpy(user_dest, kbuf, len); return len; }
整数乘法的优化
- 整数乘法(至少 10 个时钟周期)通常比加法、减法、移位和位级运算(1 个时钟周期)慢得多
乘以 2 的幂
- 对于整数变量
x
,C 表达式x << k
等价于 x×2kx \times 2^kx×2k x×14x \times 14x×14 可优化为(x << 3) + (x << 2) + (x << 1)
,或更进一步优化为(x << 4) - (x << 1)
除以 2 的幂
- 整数除法(至少 30 个时钟周期)比整数乘法更慢
相关文章推荐
- 深入理解计算机系统(2.8)---浮点数的舍入,Java中的舍入例子以及浮点数运算(重要)
- 深入理解计算机系统(1.3)------操作系统的抽象概念
- 深入理解计算机系统(2.7)---二进制浮点数,IEEE标准(重要)
- 深入理解计算机系统(3.7)---汇编世界当中过程的经典(十分重要)(难度较高)
- 深入理解计算机系统(2.8)---浮点数的舍入,Java中的舍入例子以及浮点数运算(重要)
- 深入理解计算机系统(3.8)---数组、异质结构以及指针的详解(十分重要)(难度较高)【呕心沥血版】
- 深入理解计算机系统(3.6)---汇编中精妙的流程控制(重要)(难度较高)
- 深入理解计算机系统(2.3)---整数的表示方式精解》无符号与补码编码(重要)
- cs app深入理解计算机系统:第五章 优化程序性能 几个优化的java实现
- 深入理解计算机系统(1.3)------操作系统的抽象概念
- 深入理解计算机系统(1.3)---金字塔形的存储设备、操作系统的抽象概念
- 深入理解计算机系统(3.6)---汇编中精妙的流程控制(重要)(难度较高)
- 深入理解计算机系统(3.7)---汇编世界当中过程的经典(十分重要)(难度较高)
- 深入理解计算机系统(3.8)---数组、异质结构以及指针的详解(十分重要)(难度较高)【呕心沥血版】
- 深入理解计算机系统 1.9 重要主题
- 深入理解计算机系统(2.5)---二进制整数的加、减法运算(重要)
- 深入理解计算机系统(2.3)---整数的表示方式精解》无符号与补码编码(重要)
- 深入理解计算机系统(2.6)---二进制整数的乘、除法运算(重要)【困难度高】
- 深入理解计算机系统(1.3)---金字塔形的存储设备、操作系统的抽象概念
- 深入理解计算机系统:汇编基本概念