22/8/11 深入理解计算机系统第七章
加载器运行时,它创建类似与该表的内存映像,在程序头部表的引导下,加载器将可执行文件的片复制到代码段和数据段。然后加载器跳转到程序的入口点(_start函数的地址)。这个函数定义在系统目标文件ctrl.o里。_start函数调用系统启动函数__libc_start_main,该函数定义在libc.so中。它初始化执行环境,调用用户层的main函数,处理函数的返回值,并返回内核。
加载器工作概述:
Linux系统中的每个程序都运行在一个进程的上下文中,有自己的虚拟地址空间,当shell运行一个程序时,父shell进程生成一个子进程,它是父进程的一个复制。子进程通过execve系统调用启动加载器。
加载器删除子进程现有的虚拟内存段,并创建一组新的代码、数据、堆和栈段。新的栈和堆段被初始化为0。通过将虚拟地址空间中的页映射到可执行文件的页大小的片(chunk),新的代码段数据段初始化为可执行文件的内容。最后加载器跳转到_start地址,它最终会调用应用程序的main函数。
7.10 动态链接共享库
静态链接的缺点:每个进程都要把函数的代码复制到.text段里。会极大的浪费内存。而且每次使用新版本的库,都要显示的链接一次。
共享库是一个目标模块,在运行和加载时可以加载到任意的内存地址,并和一个内存中的程序链接起来。这个过程是由动态链接器执行的,被称为动态链接。Linux用.so,windows下用.dll表示共享库。
共享库的特点:
- 在一个文件系统中每个库只有一个.so文件,所有引用该库的可执行目标文件共享这个.so文件中的代码和数据,而不是静态库内容被复制和嵌入到引用它们的可执行文件中。
- 动态链接的过程见书P484
动态链接器本来就是一个共享目标(.so),但它是静态的。
加载时,加载器遇到需要动态链接的引用,先加载和调用这个动态链接器。
假设共享库为libc.so
动态链接器执行下面的重定位:
- 重定位libc.so的文本
- 重定位可执行目标文件的所有对libc.so定义的符号的引用。
然后共享库的位置就固定了,直到程序执行完。(注意上述情况是加载后执行前)
7.11 从应用程序中加载和链接共享库
共享库的作用例子:
- 分发软件,可以用户下载共享库来更新软件。
- 构建高性能的web服务器,不用fork和execve子进程,而是可以在运行时更新已经存在的函数,以及添加新函数。
浙公网安备 33010602011771号