汇编程序生成的目标文件还不能立即执行,需要经过链接处理才能生成最终的可执行文件。链接程序的目的是将相关的目标文件链接起来,生成一个能装入操作系统中运行的统一整体或模块插件。根据链接方式的不同,链接处理可分为以下两种。
1.静态链接
静态链接是将相关的目标文件与所包含的函数库合成到一个可执行文件中,将需要调用的函数也复制到该执行文件中,实质就是一个目标文件集。
由此可见,静态链接编译出来的执行文件较大,编译时就包括所有使用的函数,因此也就不需要函数库的支持,运行简单。但后期维护起来较为困难,可移植性也较差。因为函数库升级后差异较大,就需要重新编译。对于应用程序较多的设备来说,这不是一个好的选择。
2.动态链接
源代码在名为动态链接库的目标文件中,链接程序在可执行程序中记录了共享对象的属性。当程序运行时,动态库被映射到正在运行进程的虚地址空间。动态链接程序就可以根据对象属性找到对应的函数代码,合入运行。
很明显,采用动态链接时可执行文件较小,因为在内存中只保存了一份共享对象代码,当多个进程共享对象时便可减少内存资源的消耗。
在实际软件开发中上述两种方法都可用,没有固定的限制,要结合设备自身的内存、CPU和Flash大小等因素综合考虑。在某些应用场景下嵌入式Linux软件开发中较多采用动态链接的方法,这对硬件资源有限的嵌入式设备有巨大的吸引力。这两种链接库的创建实例如下。
头文件:filestruct.h
#ifndef _FILESTRUCT_H_ #define _FILESTRUCT_H_ #include <stdio.h> #include <string.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 int writeFileStruct (const char *fName,char *buf,int bufLen,char *mode); int readFileStruct (const char *fName,char *buf,int bufLen,char *mode); #endif
源程序:filestruct.c
#include "filestruct.h" /*参数fName:文件名;buf:存放文件内容的缓冲区;bufLen:缓冲区大小;mode:读写模式,如"r""w"*/ int writeFileStruct (const char *fName,char *buf,int bufLen,char *mode) { FILE * fID = NULL; fID = fopen (fName,mode); if (fID = = NULL) { perror ("fopen fail!"); return FALSE; } rewind (fID); if (fwrite (buf,bufLen,1,fID)= = 0) { perror ("fwrite fail!"); fclose (fID); return FALSE; } fclose (fID); return TRUE; } int readFileStruct (const char *fName,char *buf,int bufLen,char *mode) { int ret; FILE *fID = NULL; fID = fopen (fName,mode); if (fID = = NULL) { perror ("fopen fail!"); return FALSE; } rewind (fID); ret = fread (buf,bufLen,1,fID); if (ret >= 0) strcat (buf,"\0"); else { perror ("fread fail!"); fclose (fID); fID = NULL; return FALSE; } fclose (fID); return TRUE; }
main.c 可由读者自行编写。一般动态库用.so 命名,静态库用.a 命名。用动态链接库编译生成的可执行文件要调用.so文件,用静态链接库编译生成的可执行文件可直接运行。
(1)静态链接库
① 编译生成目标文件:gcc -c filestruct.c。
② 创建静态库:ar cqs libfilestruct.a filestruct.o。
③ 链接静态链接库,生成可执行文件:gcc main.c -static -L. -lfilestruct -o main。
(2)动态链接库
① 编译生成动态链接库:gcc filestruct.c -fPIC -shared -o libfilestruct.so。
② 链接动态链接库,生成可执行文件:gcc main.c -L. -lfilestruct -o main。
③ 配置库的环境路径。
● 在bashrc或profile中用LD_LIBRARY_PATH定义,或在PATH中添加,总之要能在定义的环境路径中找到,然后用source加载。
● 把库路径添加到/etc/ld.so.conf文档中,然后用ldconfig加载。
● ldconfig 库文件的存放路径。