您的位置:首页 > 其它

关于链接的简单总结

2010-07-22 00:17 190 查看
  重温了《Expert C Programming》中第五章——对链接的思考,写点读书笔记。

1、链接器

  按照分而治之的思想,编译器分成六七个部分来执行不同的功能,而这些程序是由一个叫做“编译器驱动器(compiler driver)”控制程序来调用。这几个部分按照执行的先后顺序分别是:预处理器(preprocessor)、语法语义检查器(syntactic and semantic checker)、代码生成器(code generator)、汇编程序(assembler)、优化器(optimizer)、链接器(linker)。

  编译生成的目标文件是不能直接执行,它必须首先被载入到链接器中,然后链接器确认main函数为初始进入点,把符号引用绑定到内存地址,把所有目标文件集中在一起,再加上库文件,从而产生了可执行文件。

  以前的UNIX系统是这样的:当链接程序时,需要使用每个库函数的一份拷贝被加入到可执行文件中。这点方式我们称之为:静态链接。但是一种更为现代和优越的方式越来越多地被我们所采用,这种方式叫做:动态链接。动态链接允许系统提供一个庞大的函数库几何,可以提供很多不同的服务。接下来具体讨论一下这两种方式的特点。

2、静态链接与动态链接的特点

  我们再来回顾一下这两种方式的概念:如果函数库的一份拷贝是可执行文件的物理组成部分,那么我们称之为静态链接;如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,那么我们称之为动态链接。收集模块准备执行的三个阶段为:链接-编辑、载入和运行时链接。所以,静态链接的模块是在链接编辑并载入的,而动态链接的模块是被链接编辑后再载入,并在运行时进行链接才可以运行。这就是动态链接的妙处,即使你链接了函数库,但是你没调用到库,也不会带来额外的开销,只有当你运行了并调用了才把库函数映射到进程中来。但是即使是在静态链接中,整个库文件也并没有全部装入到可执行文件中,装入的当然只是所需要的函数而已。

  动态链接的优点:

  1) 根据我们上面的描述,动态链接所需要的磁盘空间比静态链接小。

  2) 动态链接可以实现进程中的共享。比如说,在系统中有5个进程都同时用到一个函数库中的某一个函数,那么第一个调用该函数的进程运行之后,操作系统把该函数库相应的文本段映射到内存中,这个时候其他需要调用该函数的进程都可以共享该函数了,而不需要每次调用都重新映射,实际上就是提高了效率。换成是静态链接,5个进程需要5份拷贝映射到内存中,这就耗费了更多的物理内存,引起了更多的换页。

  3) 方便更新。你可以随时更新函数库,需要调用到函数库的程序不需要重新编译,只是在运行时链接相应的函数,仅此而已。区别

3、如何创建静态库和动态库

  拿经典的hello world为例子。编辑了下面一个简单的C文件:

#include <stdio.h>

void printHelloWorld(void)
{
printf("Hello, world!\n");
}


1)编译让它生成一个.o文件,这是创建静态库和动态库必须的一步:

ken@Linux:~/test$ gcc -c helloworld.c


2)生成静态库,静态库的命名规范为:lib为前缀,.a为后缀,libname.a就是格式了。ar就是创建静态库的命令:

ken@Linux:~/test$ ar cr libhelloworld.a helloworld.o


3)接下来创建一个.c文件来调用函数库的函数:

#include <stdio.h>

int main()
{
printHelloWorld();
return 0;
}


4)这个时候可以进行编译和执行了:

ken@Linux:~/test$ gcc -o helloworld hello.c -L. -lhelloworld


-L. 表明是静态链接的目录是在当前目录下,链接库必须用-l加库的名字,就是去掉libhelloworld.a的前缀和后缀。

  接下来看看创建动态库的方法:

ken@Linux:~/test$ gcc -shared -fPCI -o libhelloworld.so helloworld.o


而动态链接的执行方法和静态是一样的:-)

NED
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: