您的位置:首页 > 职场人生

程序员的自我修养 链接、装载、与库——读书笔记

2017-04-19 17:33 519 查看
一.预备知识

1.为了协调CPU、内存和高速的图形设备 -> 北桥 -> 有相对低速的设备连在北桥上 -> 南桥,专门处理低速设备 -> CPU频率被4GHz天花板限制,增加CPU数量 -> 对称多处理器 -> 成本高,多处理机之间共享昂贵缓存,多个核 ->多核处理器

2.将用于管理计算机本身的软件成为系统软件



平台性的:操作系统内核 驱动程序 运行库 系统工具

程序开发性的:编译器、汇编器、链接器等开发工具和开发库

运行库

操作系统内核

硬件

3.将计算机上有限的物理内存分配给多个程序使用,但问题是地址空间不隔离、内存使用效率低、程序运行地址不确定。

加中间层的方法可以避免问题,把程序给出的地址看作是虚拟地址,通过映射,将虚拟地址转换为实际物理地址。

分段 将程序所需的内存空间大小的虚拟地址映射到某个物理地址,程序A、B被映射到两块不同物理空间区域且无重叠,解决了地址空间不隔离、程序运行地址不确定的问题

根据局部性原理,程序在运行时,在某个时间段内,只是频繁用到一小部分数据,分页 将地址空间人为地等分成固定大小的页共程序使用,提高内存使用效率

4.

进程:所有应用程序以进程的方式运行在比操作系统权限更低的级别,有独立的地址空间,进程之间地址空间相互隔离

线程:程序执行流的最小单元,

由线程ID、当前指令指针PC、寄存器集合、堆栈构成

一个进程由一个或多个线程组成,各个线程之间共享程序的内存空间(代码段、数据段、堆)及一些进程级资源(打开文件和信号)

线程私有:局部变量、函数参数、线程局部存储数据

线程之间共享:全局变量、堆上的数据、函数里的静态变量、程序代码打开的文件

线程状态:运行、就绪、等待

线程调度:

- 轮转法 让各个线程轮流执行一小段时间的方法

- 优先级调度 改变优先级的方法:指定优先级、根据进入等待状态的频繁程度提升或降级优先级、长时间得不到执行而提升优先级

5.线程安全

同步:在一个线程访问数据未结束时,其他线程不得对同一个数据进行访问,将数据的访问原子化

同步最常见方法:锁,线程访问数据或资源前先获取锁,并在访问结束之后释放锁,锁被占用时,获取锁的线程等待,直到锁重新可用

信号量 占用/非占用

互斥量 必须由同一个线程释放、获取的信号量

临界区 仅限于本进程,其他进程无法获取的互斥量

编译器优化时,可能为了效率而交换毫不相干的两条相邻指令的执行顺序,使用volatile关键字阻止过度优化

1.阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回

2.阻止编译器调整操作volatile变量的指令顺序

二.编译和链接

编译 + 链接 = 构建

预编译 处理以‘#’开始的预编译指令,展开宏定义 #define #if #endif

删除注释 添加行号标示

编译

词法分析 将源代码字符序列分割成一系列记号

语法分析 用语法分析器将产生的记号进行语法分析,产生语法树

语义分析 将语法树上的类型不符的插入相应结点,做隐式转换

生成中间代码 编译器前端

汇编 编译器后端 将汇编代码转变为机器可执行指令

链接 将源代码模块独立地编译,然后将其组装起来,将目标文件链接形成可执行文件

地址和空间分配

符号决议

重定向 确定全局变量和函数最终运行时的绝对地址

三.目标文件

ELF executable file

文件头 描述文件属性 段表 重定位表

代码段 .code .text 源代码编译后的机器指令

数据段 .data 已初始化的全局变量、局部静态变量

.bss 未初始化的全局变量、局部静态变量

段表:数组中每个元素都是结构体,包括段名、类型、加载地址、相对于文件头的偏移量、段大小、链接信息

重定位表:需要重定位的信息

函数、变量需要独特的符号名,防止类似的符号名冲突,C++采用命名空间的方法解决符号冲突,Objective-C 采用加前缀方式。

函数签名:包含了一个函数的信息,包括函数名、参数类型、所属类、名称空间及其他信息

符号分为强符号,和弱符号。强符号不可名称重复,弱符号(未初始化的全局变量)可以符号名相同。

对符号名的引用分为强引用和弱引用,强引用表示如果找不到符号定义会报错,弱引用不报错,默认为0或某个特殊值。

——–未完待续——–
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: