读书笔记:程序员的自我修养

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
– 模块内指令,数据:相对地址访问 – 模块间指令,数据:间接跳转(GOT, global offset table)
• GOT表实现的动态链接会造成性能下降5%左右, 所有又延迟绑定的技术,PLT(Procedure Linkable Table) • ldd 查看程序依赖那些共享库,有时候会看到 vfso,这是虚拟出来的共享库,提供sysenter入 口,加快栈保存
– 创建虚拟空间,即创建各种数据结构 – 建立虚拟空间与可执行文件的映射关系 – 将CPU指令寄存器设置成可执行文件入口 – 具有相同权限的段可能share同一个VMA (virtual memory area), 放入同一个物理页面
• 动态库链接 –fPIC (position indepent code)
– .init : 在main函数执行之前执行 – .fini : 在main函数返回之后执行
• 静态库就是一组目标文件的集合:
• ar –t *.a : create, modify or extract from archives
• 链接控制脚本:控制链接行为,比如入口, 如何merge各个段,是否丢弃某些段等 • 进程启动:
• 动态链接:动态链接器主动load共享对象 • 动态加载:程序运行过程中利用动态链接器提供的 API加载库 • 动态链接
– 节省内存 – 方便升级特定模块 – 方便重用
• 装载时重定位无法再各个进程之间共享代码,效率 略高;地址无关代码可以在各个进程间共享代码, 效率略低 • ldconfig可以刷新/lib, /usr/lib等目录加载共享库,所 以可以将共享库拷贝到上述目录中然后加载
• ELF file types (shell command : file )
– – – –
• • • • • •
Re-locatable file : code, data (*.o), static lib Executable file : (runnable) Shared object file : *.so Core dump file
• 定义TLS数据
– 隐式定义:_thread int num; – 显示定义:pthread_key_create
• errorno是TLS的一种,单线程时候errorno返 回全局唯一地址;多线程时候每个线程 errorno返回的地址都不同
• 每个便一单元都会有一个全局变量初始化函数 指针,程序连接时候将所有这些函数指针收集 起来然后由do_global_ctor_aux逐个执行 • 定义全局构造器:

So we can know why return value cannot differentiate overloading method in c++, because method signature does not include return type
• 强符号和弱符号
– – – – –
• • • •
强符号:初始化的全局变量,函数 弱符号:未初始化的全局变量 __attribute__((weak)) 可以显式定义一个弱符号 强符号不允许重复定义 弱符号如果有重定义则分配空间按照大的那个
不允许未定义的强引用 允许未定义的弱引用 __attribute__((weakref)) 可以显示定义弱引用 弱引用的好处是允许程序link用户自定义的方法,库;如果 用户未定义的时候,则会link系统默认的方法,库
• 强引用和弱引用
• gcc –g 加入调试信息到执行文件 • 标准调试信息格式:DWARF (debug with arbitrary record format) • 调试信息会比较大,[strip x]可以去除调试信息,但 是不建议因为线上调试很困难 • ld –e
– 一般采用两步链接(two pass linking)
– ctor_t __attribute__((section(“.ctors”))) void (*)() – void x() __attribute__ ((constructor)) 可以定义全局 构造器 – 似乎无直接的意义,因为定义全局变量一样能够解 决,而且更加直观
• Memory barrier
• 阻止编译器对指令进行调序,barrier两端的代码一定不会被调序
• 编译过程
– 预编译 – 编译 – 汇编 – 链接
• 可执行文件格式:
– Windows : PE (portable executable) – Linux : ELF (executable linkable format) – 均来自于COFF (Common file format)
ELF header .text (program text) .bss (uninitialized global data, not occupy space) .data (initialized global and local static data) .rodata (read only data) .comment
• 动态链接
– 启动动态链接器本身 – 加载需要的共享对象 – 重定位和初始化
• 系统自举之后会依次加载所有的动态库,这些 动态库之间又有相互依赖,这些依赖关系构成 了一个图,通过遍历图可以按照正确顺序加载 所有库 • 全局符号介入(global symbol interpose):当一 个符号需要被加入全局符号表时,如果该符号 已经存在,则将后来的忽略
• 线程优先级的改变
– 用户设定优先级 – 根据等待的频繁程度提升或者降低优先级,频繁等待I/O的线程被 提升的可能性就大 – 长时间得不到执行的线程被提升优先级
• Linux的执行实体是Task,不同Task之间可以share内存和文 件,所以本质上就是线程 • Volatile
• 阻止编译器将变量放入寄存器而不写会 • 阻止编译器将操纵该变量的语句调序 • 修饰代码的时候则是指不要对以下语句做任何优化
程序员的自我修养
读书笔记 shiquany@gmail.com
• 南桥:链接慢速设备,比如键盘,USB,磁盘 • 北桥:链接快速设备,比如CPU,Memory • 磁盘:每个盘片有两个盘面,每个盘面划分为多个磁道, 每个磁道划分为多个扇区,一般每个扇区存储512B数据 • 程序直接访问物理内存;分段;分页 • 线程与可以调度的进程之间的关系:1 VS 1, n vs 1, m VS n,其中RedHat开发的NPTL是第一种,所以看起来线程频 繁切换的调度开销会比较大 • 通过控制.ctor and .dtor 应该可以控制全局变量的析构顺序。 并且如果将所有的全局变量定义在一个cpp里面,其余只 是引用应该可以保证构造和析构顺序的。但是这有时候好 像挺难的,因为不符合模块化设计原则
• 压栈顺序:参数,返回地址 • 返回对象在VC和GCC均会被拷贝两次,所以 要多使用引用和指针 • 进程执行函数顺序
– lib_start_main – main – atexit
• Bound指针:第一个是raw value,第二个是存 储下限值,第三个是存储上限值,容易检查越 界访问 • Alloca在堆被初始化之前可以用来分配内存, 该内存是分配在栈上的,程序退出自动释放 • OS拥有每个打开文件对象的信息,OS可以解 释每个FD或者句柄到内核文件对象的映射 • 线程不安全函数:strtok,该函数使用了静态 局部变量,strtok_r是安全的,STL stream库貌 似使用了不安全函数
• COMMON块
• 未初始化的全局变量是弱符号,在link之前其大小是未 知的(其他文件可以定义同名的符号),因此放在 COMMON块,最终link的时候放在.bss里面
• 每个类模板都是一个section这样就可以解决模 板重复链接占用空间过大的问题,因为相同的 section会只保留一个 • 如果两个section名字相同但是内容不同,会有 warning • 有个特殊的段
• Ld 静态链接时的一些特殊地址
– – – –
• • •
__executable_start : 程序起始地址 __etext : 代码段结束地址 __edata : 数据段结束地址 __end : 程序结束地址
foo -> _foo (C programming ) foo -> _foo_ (Fortran) Int C::foo (string) : _ZN1C3fooEs
• 读取所有输入文件,计算文件中各个段所需空间 • 将各个文件的同名段merge起来,并根据全局符号表调整地址
– 实际运行环境中,ld常被collect2代替,主要处理全局变 量构造/析构的问题
• 绝对地址修正:S+A • 相对地址修正:S+A-P
– S:符号地址 – A:被修正位置的值 – P:被修正的位置
• void __attribute__((constructor(1))) foo();
– 指定动态库加载前需要做的工作 – 指定优先级,数字小的先运行
• void __attribute__((destructor(4))) foo();
• 指定动态库退出后需要做的工作 • 指定优先级,数字大的先运行
– – – – – _ZN : fixed prefix Size of namespace or class name Name of namespace or class name E : fixed string Para type
• Name decoration && functioFra Baidu bibliotek signature
• ELF file structure
• 自定义段:
– __attribute__((section(“x”))) int global_var = 3; – __attribute__((section(“x”))) void print();
• ELF
– 文件格式定义 : /usr/include/elf.h – 文件中定义Magic number,在文件和一些内存 结构中常常定义一些magic number用于确保该 文件是有效的或者放置内存被写坏
相关文档
最新文档