因为p 不是一个内置的外壳命令,所以外壳会认为p 是一个可执行目标文件,通过调用某个驻留在存储器中称为加载器(loader) 的操作系统代码来运行它.加载器将可执行目标文件中的代码和数据从磁盘拷贝到存储器中,然后通过跳转到程序的第一条指令或入口点来运行该程序。这个将程序拷贝到存储器并运行的过程叫做加截(loading) 。
在32 位Linu系统中,代码段总是从地址Ox08048000 处开始。数据段是在接下来的下一个4KB 对齐的地址处。运行时堆在读/写段之后接下来的第一个4KB 对齐的地址处,并通过调用malloc 库往上增长。
共享库是致力于解决静态库缺陷的一个现代创新产物。共享库是一个目标模
块,在运行时,可以加载到任意的存储器地址,并和一个在存储器中的程序链接起来。这个过程称为动态链接(dynamic linking) ,是由一个叫做动态链接器(dynamic linker) 的程序来执行的。
共享库也称为共享目标 ,在Unix 系统中通常用. s。后缀来表示。微软的操作系统大量地利用了共享库,它们称为DLL (动态链接库)。
首先,在任何给定的文件系统中,对于一个库只有一个.5。文件。所有引用该库的可执行目标文件共享这个.5。文件中的代码和数据,而不是像静态库的内容那样被拷贝和嵌人到引用它们的可执行的文件中。其次,在存储中,一个共享库的.text 节的一个副本可以被不同的正在运行的进程共享.
给链接器如下特殊指令:
unix> gcc -sbared -ÎPIC -0 libvector.so addvec.c multvec.c//-fPIC 选项指示编译器生戚与位置无关的代码 -5hared 选项指示链接器创建一个享的目标文件。 unix> gcc -0\'p2 main2 .c ./libvector.so//这样就创建了一个可执行目标文件p2 ,而此文件的形式使得它在运行时然后,动态链接器通过执行下面的重定位完成链接任务:
.重定位libc.5 。的文本和数据到某个存储器段。 ·重定位lib飞Tector.5 。的文本和数据到另一个存储器段。 ·重定位p2 中所有对由libc.5。和libvector.5。定义的符号的引用。 7.11 从应用程序中加载和链接共享库 #include <dlfcn.h> void *dlopen(const char *filename , int flag); 返回若成功则为指向句柄的指针,若出错则为NULL 。dlopen 函数加载和链接共享库filename 。用以前带RTLD GLOBAL 选项打开的库解析filename 中的外部符号。如果当前可执行文件是带rdynamic 选项编译的,那么对符号解析而言,它的全局符号也是可用的。
#include <dlfcn.h> void *dlsym(void *handle , char *symbol); 返回若成功为指向符号的指针,若出错则为NULL 。dlsym 函数的输入是一个指向前面已经打开共享库的句柄和一个符号名字,如果该符号存在,就返回符号的地址,否则返回NULL 。
#include <dlfcn.h> int dlclose (void *handle); 返回:若成功为0 ,若出错则为1.如果没有其他共享库正在使用这个共享库, dlclose 函数就卸载该共享库。
#include <dlfcn.h> const char *dlerror(void); 返回如采前面对dlopen 、dlsym 或dlclose 的调用失败,则为错误消息,如果前面的调用成功,则为NULL.dlerror 函数返回一个字符串,它描述的是调用dlopen 、dlsym 或者dlclose 函数时发生的最近的错误,如果没有错误发生,就返回NULL 。
7.12 与位置无关的代码多个进程是如何共享程序的一个拷贝的呢?一种方法是给每个共享库分配一个事先预备的专用的地址空间片(chunk) ,然后要求加载器总是在这个地址加载共享库。一种更好的方法是编译库代码,使得不需要链接器修改库代码就可以在任何地址加载和执行这些代码。这样的代码叫做与位置无关的代码.
无论我们在存储器中的何处加载一个目标模块〈包括共享目标模块),数据段总是被分配成紧随在代码段后面。为了运用这个事实,编译器在数据段开始的地方创建了一个表,叫做全局偏移量.
7.13 处理目标文件的工具 .AR: 创建静态库,插入、删除、列出和提取成员。 .STRINGS: 列也一个目标文件中所有可打印的字符串. .STRIP: 从目标文件中删除符号表信息。 .NM: 列出一个目标文件的符号表中定义的符号。 .SIZE: 列出目标文件中节的名字和大小。 .READELF: 显示一个目标文件的完整结构,包括且F 头中编码的所有信息。包含SIZE 和NM 的功能。 .OBJDUMP :所有二进制工具之母。能够显示一个目标文件中所有的信息。它最大的作用是反汇编.text 节中的二进制指令。 .LDD: 列出一个可执行文件在运行时所需要的共享库。