笔记—《程序员自我修养》

《程序员自我修养》 笔记

温故而知新

平坦内存模型存在的问题

  • 进程之间地址空间不隔离
  • 多进程时, 内存碎片多(分页), 内存利用效率低(缓存命中率)
  • 程序运行的地址空间不确定

分段

提高缓存命中率
读写权限隔离
提高内存利用效率(多个运行的线程可以共享一份代码段)

分页

提高内存利用率,减少内存碎片
和虚拟内存管理机制一起解决了内存不连续的问题(分配的内存一般是虚拟内存,在第一次使用虚拟内存发生缺页中断中才会真正分配物理内存)

线程 与 进程

Linux 下线程与进程都是使用同一个结构体task_struct来表示的,线程之间共享的内存结构来区分线程和进程之间的并发程度,内核线程 复制阻塞情况下的线程切换, 非阻塞的线程切换在用户态处理。

线程的私有空间

Stack
寄存器
线程局部存储

预处理,编译,汇编,链接

静态链接

目标文件(ELF格式)

.o 可重定位文件 有一个重定位表 rel.text 用于重定位符号
可执行文件
.so 共享目标文件,用于动态链接

文件内容

BSS 未初始化的静态变量
COMMON 未初始化的全局变量(因为暂时不知道需要多少内存)
DATA 初始化的全局变量的静态变量
TEXT
RODATA
符号表(重定位和符号决议)
文件头 版本 大小 偏移量 magic number
重定位表 前置声明的重定位

强符号 与 弱符号

前置声明是弱符号, 定义/初始化是强符号,在副号决议的时候会优先对应强符号,多个强符号会报错冲突。

符号修饰

C++的重载 对符号名的影响
命名空间 对符号名的影响

extern

函数声明规范
函数,变量的 外连接性质

地址和空间分配 + 重定位和符号决议 = 链接

  1. 扫描输入目标文件获得各个段的长度,分配内存并维护一个全局符号表
  2. 根据全局符号表和重定位表 完成副号决议 和 重定位

main 函数之前和之后的内容

初始化进程环境,堆分配初始化,传递main 的参数,全局变量的初始化等。
.init 段:
.fini 段:

可执行文件的装载与进程

32位平台下的4G内存空间,1GB内核,1GB用户态。

加载方式-页映射

页映射是虚拟存储机制的一部分,随着虚拟存储的发明而诞生,数据和指令按页划分完毕后装载,如果程序使用物理地址直接进行操作,那么每次装入页都要进行重定位。

进程的建立

创建一个独立的虚拟地址空间(分配一个页目录)
建立空间和可执行文件的映射关系(进程中VMA映射到ELF的.text段)
CPU寄存器设置为可执行文件入口地址

进程装载细节

把相同权限的段合并在一起映射

堆栈分配

猜你喜欢

转载自www.cnblogs.com/joeylee97/p/9169099.html