作者mshockwave (夏克维夫)
看板LinuxDev
标题Re: [问题] 连结&载入器,分段分页,Binding关系
时间Sat Jul 11 20:41:09 2015
※ 引述《gigigigi (gigigigi)》之铭言:
: 何谓Binding
: Def: 决定程式执行的起始位址。
: 即:程式要在内存的哪个地方开始执行。
: 可能的Binding时期有三个:
: 1. Compiling Time
: 2. Loading Time
: 3. Execution Time
: 3-1 : Dynamic Binding
: 3-2 : Dynamic Loading
: 链接器( Linker )是把不同部分的代码和数据,收集、组合成为一个可加载、可执行的文
: 件。
: 加载器( Loader )把可执行文件从外存装入内存并进行执行
: MMU : 分段 + 分页
: 分段 - 逻辑位址 -> 线性位址
: 分页 - 线性位址 -> 实体位址
: _________________________________________________________________________________
: 我被上面情况给搞的有点乱 , 有下面几点疑惑
: 1.
: Binging 三个时期程式位址都算是虚拟位址?
是的 除非你玩的是没MMU的处理器
: Compiling Time 位址是由编译器计算出来?
不算是 其实是由连结器那边设定的
: Loading Time 是由 加载器 计算出位址?
: Execution Time : 位址是 Local Address + Base Register ?
小弟不才 可能不完全正确 但其实元PO问的事情没那麽复杂
用一句话回答的话就是:把一切交给虚拟位址就对了!
基本上会考虑到实体位址的就只有一位:核心
包括编译器连结器在内 都是用虚拟位址在思考
而我刚刚讲的 编译完的位址 其实是由叫做linker script的东西设定的
这些script是ld在编译的链结时期读取的
(script路径可由 ld --verbose | grep SEARCH_DIR 得知)
决定的事情包括最重要也最基本的:执行档的开头要载到哪一个位址(虚拟位址)
也多亏了虚拟位址 每一个执行档 档案里写的开始执行位址都可以一样
反正实际在记忆体中的位址是由核心分配的嘛
linker script其实常常用在一些很hack的地方
例如linux kernel 会把某些符号在链结时期改成另外一个名字
Mozilla B2G (Firfox OS)也利用linker script
把一些重要的libc符号 映射到他们自己实作的版本 说可以避免concurrency(?
: 2.
: 目前Linux 是用MMU 段式 + 页式 ?
这个问题蛮好玩的 因为x86大力鼓吹段式(segment) 但Linux为了跨平台着想
因为很多RISC家族根本没有segment的概念 所以是采用页式(page)
: Linux 跟 Binding三个时期有关系嘛?
: Binding三个时期技术是早期的技术嘛? 目前有机会使用到嘛?
其实我不太知道你这边的Binding是什麽意思
因为小弟是搞编译器的 第一个就想到Name Binding XDD
: 3.
: 链接器( Linker )是把不同部分的代码和数据,收集、组合成为一个可加载、可执行的文
: 件。
: 我认知编译出执行文件使用 objdump -d 就可以看到虚拟位址 , 就位址是ld Linker
: 计算出来的嘛? 如果是它是属於哪个Binding?
: gcc -g test.c
: 使用 objdump -d ./a.out
: 08048414 <main>:
: 8048414: 55 push %ebp
: 8048415: 89 e5 mov %esp,%ebp
: 8048417: 6a 03 push $0x3
: 8048419: 6a 02 push $0x2
: 804841b: e8 e1 ff ff ff call 8048401 <foo>
: 8048420: 83 c4 08 add $0x8,%esp
: 8048423: b8 00 00 00 00 mov $0x0,%eax
: 8048428: c9 leave
: 8048429: c3 ret
: 804842a: 66 90 xchg %ax,%ax
: 804842c: 66 90 xchg %ax,%ax
: 804842e: 66 90 xchg %ax,%ax
: 加载器( Loader )把可执行文件从外存装入内存并进行执行 <-- 这过程有经过虚拟位址
: 映射实体位址转换嘛?
虚拟位址的映射(到实体位址)完全是执行的时候做的事喔
: Linux 系统的加载器( Loader ) 这是位於 linux kernel 里面?
是的 加载执行档一定是作业系统的事
ld.so的角色呢(不是编译时期的ld)?他是负责解析动态函式库(.so)的相关事情
例如帮忙resolve现在执行需要的so并加以载入
那那个so载入的位址呢?前面讲过 每个执行档编译出来 开始的虚拟位址可以一样
但so的虚拟位址并不是写死的
其中的技术就是PIC(Position independent code) 也就是编译so时下的 -fPIC
就如字面上讲的 他并不是绝对位址 而是相对位址
因此ld.so就可以把他载到执行位址空间的任何一个地方
详细的技术比较复杂一点 这边写不下 推荐原PO去读 程式设计师的自我修养
那本书真的很珍贵 因为我竟然发现 这麽重要的技术 竟然很少原文书
上述回答可能有误 请各位大大多多指教了<(_ _)>
: 谢谢
--
1F:推 SORAChung: aldnoah zero演完了,下一季是aldnoah stay night吗
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.155.231
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/LinuxDev/M.1436618483.A.F00.html
2F:→ descent: 其实学校系统程式就是教这个, 只是我不知道为什麽他们 07/11 21:13
3F:→ descent: 都不教真实世界的东西, 而是弄一个教学用的平台 07/11 21:14
4F:→ descent: 观念虽然一样, 但却没有连接到真实世界的感觉 07/11 21:14