该书填补了中国书籍上Linker & Loader 空缺, 降低了难度, 而且写的非常友好.
我觉得, 如果要对编译, 链接与装载更好的了解, 结合CSAPP, LinuxC一站式编程 这方面的知识来一起读, 就完美了.
因此, 我写了篇博客, 总结了这个过程: C/C++编译链接与装载深入浅出
http://yonghaowu.github.io/2016/05/09/Linker_And_Loaders/
http://yonghaowu.github.io/2016/05/09/Relocation_Symbol_Decoration/
编译的详细过程
以hello.c的源文件为例, C/C++编译, 链接与装载的流程是
gcc -E 将hello.c预处理, 把所有的宏展开, 解析#ifndef, 删除注释等, 得到hello.i文件.
gcc -S 将hello.i编译成汇编文件hello.s
gcc -c 汇编器as将hello.s编译成成目标文件hello.o
gcc 链接器ld将hello.o链接成可执行文件a.out
最简单的汇编程序
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $77, %ebx
int $0x80
将这个文本保存成hello.s, 再用汇编器(Assembler)把汇编程序中的助记符翻译成机器指令, 生成目标文件hello.o
$ as hello.s -o hello.o
然后用链接器(Linker, 或Link Editor)ld把目标文件hello.o链接成可执行文件hello:
$ ld hello.o -o hello
这个程序只是做了一件事: 退出.
退出状态(Exit Status)为77, 在Shell中可以用特殊变量$?得到上一条命令的退出状态
$ ./hello
$ echo $?
77
.section到ELF文件
.section会成为目标文件的Section
简单起见, 以上汇编程序只是想告诉大家, 注意以上的.section后的.data与.text
汇编程序中以.开头的名称不会被翻译成机器指令, 而是给汇编器一些特殊的指示, 称为汇编指示(Assembler Directive)或伪操作(Pseudo-operation), 由于它不是真正的指令所以加个“伪”字.
.section指示把代码划分成若干个段(Section), 程序被操作系统加载执行时, 每个段被加载到不同的地址, 具有不同的读、写、执行权限。 .data段保存程序的数据, 是可读可写的, C程序的全局变量也属于.data段. 本程序中没有定义数据, 所以.data段是空的
所以, 我们的hello.c源代码经过gcc -S 翻译后, 就得到伪操作以及一些运算指令(hello.s). 接着, 使用as hello.s根据段信息等得到目标文件hello.o, 目标文件由若干个Section组成, 我们在汇编文件中声明的.section会成为目标文件的Section, 此外汇编器会自动添加一些Section(比如符号表).
C程序编译后的执行语句都翻译成机器指令放在.text段, 已初始化的全局变量和局部静态变量放在.data段, 未初始化或者默认初始化(即是0)的全局变量和局部静态变量放在.bss的段里, 有.bss段的目的是为了节省内存空间, 因为都为0, 只需要为它们预留位置即可.
为什么不把指令跟数据全部放在一个section呢?
各个Section可以划分权限, 如.data为可读可写, .rodata与.text只可读.
指令跟数据划分得更细, 可以让缓存的命中率提高.
共享资源. 当多个相同的进程同时运行时, 可以共享.text, .rodata等. 当进程里有很大图片, 文本等资源时就可以节省大量空间.
目标文件是ELF文件
ELF(Executable and Linking Format)是一个开放标准, 各种UNIX系统的可执行文件都采用ELF格式, 它有四种不同的类型:
可重定位的目标文件(Relocatable, 或者Object File), Linux的.o, Windows的.obj
可执行文件(Executable), Linux的.out, Windows的.exe
共享库(Shared Object, 或者Shared Library), Linux的.so, Windows的.DLL
核心转储文件(Core Dump File)a, Linux下的core dump
大家想想, 当我们以前编译多个文件时, 就会有多个目标文件. 当A文件使用B文件的函数时, 两个目标文件, 是如何通信呢? 你会怎么设计呢?
下一篇我们讲解, 重定位, 重定位表, 符号等.
参考资料
本文几乎可以算是对"Linux C一站式学习", "程序员的自我修养-链接装载与库"的归纳整理.
好书, 结合CSAPP, LinuxC一站式编程来读, 就完美了
《程序员的自我修养》热门书评
-
平中见奇:程序员提升自己的参考方法
83有用 2无用 Stanley 2009-06-27
老实说,在2002年还在上大学的时候,我把技术类书籍分成了三六九等,从值得看到最不值得看到顺序如下:1. 在美国工作的中国人使用中文编写的书籍:因为作者的眼界相比国内更加宽广,而字里行间流淌着中国人的思维方式,没有理解文化表达方面的障碍,行文相对活泼2. 在美国工作的人使用英文编写的书籍3. 在中国...
-
给每个新手的修养之道
70有用 7无用 你们都是坏人 2009-11-28
如果你是高手,Linux Hacker或者geek,请绕行但如果你是新手如果你曾好奇过windows系统目录下和软件目录下大堆大堆的dll文件是什么如果你曾疑惑过我写下的代码经历的怎样的历程最后怎样到达了内存,编译器每天用,它到底做了什么如果你已经学习或接触了C,汇编,计算机结构,但还是没办法把三者...
-
推荐linux c/c++程序员一读
61有用 1无用 zoufeiyy 2009-05-20
关于《程序员的自我修养》这本书,最初是在和博文的周筠老师MSN上谈起,当时听周老师提及这本书是一本关于链接和装载等系统软件知识的书籍,当时就很感兴趣,因为这方面的书在国内真的见得很少,一方面这种书似乎跟做应用开发的有距离,毕竟如果只是用用C#、Java,似乎没什么必要关心编译器、链接器在做些什么,特...
-
莫等用时再读书
36有用 3无用 云风 2009-06-01
今年二月份拿到这本书的电子稿时,还不是现在这个名字。《程序员的自我修养》这个名字听起来比原来的那个名字感觉好一些,但又让人感觉有点不知所谓。还是副标题直接:《链接、装载与库》。我更愿意接受这样的一个名字,有如那本多年前读过的英文经典:《Linkers & Loaders》。那段时间很忙,一直...
-
something after read
18有用 2无用 veryzhang 2009-11-17
今天花了一天的时间从头到尾翻了一遍, 跳过了那些有X86汇编的部分, 和分析C++ CRT中解构析构的部分, 其他的都读了一遍.读完之后唯一的感觉就是: 此书非读不可, 而且要经常读.毫无疑问作者对于链接, 装载和库这三个方面是有深刻的认识的, 于深度和广度都无可挑剔, 而且组织文字的能力也属上乘,...
书名: 程序员的自我修养
作者:
出版社: 电子工业出版社
副标题: 链接、装载与库
出版年: 2009-4
页数: 459
定价: 65.00
装帧: 平装16开
ISBN: 9787121085116