2011年3月30日星期三

在Linux下如何创建自己的函数库

想建个函数库,把自己常用的一些函数包括进去,在使用时include一下就行了,应该怎么构建?另外,我看到常用的一些函数库,如math.h,里面只有一些函数的声明,那么执行部分在哪里?又是如何实现调用的?初学编程,谢谢各位了! 

我自己以前写的一点东西.可能对你有用吧! 

如何为Linux增加库

一. 静态库
在Linux下的静态库是以.a为后缀的文件。
1. 建静态库
h1.c 源文件
#include <stdio.h>
void hello1()
{
printf(“the first hello!\n”);
}
h2.c 源文件
#include <stdio.h>
void hello2()
{
printf(“the second hello!\n”);
}
2.主程序
hello.c 源文件
int main()
{
hello1();
hello2();
return 0;
}
输入命令:
gcc –c h1.c
gcc –c h2.c
ar –r libhello.a h1.o h2.o
ar –s libhello.a
ranlib libhello.a
最后再
gcc –static hello.c –L. –lhello –o hello即可生成可执行文件。注意要使用-static参数,否则生成的仍然是动态类型的文件,不过对于hello这个库则是采用静态方式来使用的而已。

二. 动态库
1.建动态库
#include <stdio.h>
void hello1()
{
printf(“the first hello!\n”);
}
h2.c 源文件
#include <stdio.h>
void hello2()
{
printf(“the second hello!\n”);
}
2. 主程序
hello.c 源文件
int main()
{
hello1();
hello2();
return 0;
}
输入命令:
gcc –fPIC –g –c h1.c –o libh1.o
gcc –fPIC –g –c h2.c –o libh2.o
gcc –g –shared –W1 –o libh1.so libh1.o –lc
gcc –g –shared –W1 –o libh2.so libh2.o –lc
然后再将主程序与库相连进行编译
gcc –g hello.c –o hello –L. –lh1 –lh2
最后再将当前路径放到库查找路径中去
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATY
最后再执行./hello即可运行。 

三. 动态库的查找过程
一旦连接器完成了自己的初始化工作,就查找程序所需要的库的名字。程序头中有一个指针指向dynamic段,它包含了动态连接的信息,dynamic段中的DT_STRTAB指向一个字符表,而其中的DT_NEEDED包含了一个相对于字符表的偏移,指向所需要的库名。
对于每一个库,连接器首先查找库文件位置,从本质上说是一个相当复杂的过程。DT_NEEDED所描叙的库文件名一般类似libXt.so.6 (Xt开发包, 版本6),库文件可能在任意的库文件目录中,还也可能有重名的文件。在我的系统中,这个库的实际文件名是/usr/X11R6/lib/libXt.so.6.0,最后的“.0”表示次版本号。

连接器查找下列几个地方:

l 首先查看 .dynamic 段是否包含了一个叫DT_RPATH的项(它是一个以冒号分隔的库文件搜索目录列表)。这个项是在程序被连接器连接时,由命令行开关或者环境变量添加上去的。它常应用于子系统中,比如像数据库应用,我们要装载一些程序集合以及支持库到一个目录中去的时候。

l 查看是否存在环境变量 LD_LIBRARY_PATH(它是一个以冒号分隔的库文件搜索目录列表)。这个项可以帮助开发者建立一个新版本的库,把他的路径添加到LD_LIBRARY_PATH中,把它和现存的可连接程序一同使用,用来测试新的库,

l 连接器查看库高速缓存文件 /etc/ld.so.conf ,它包含了库名和路径的一个对应列表,如果库名存在,连接器就使用它对应的路径,用这个查找方法能够找到大部分的库(文件名不需要和要求完全符合,这点可以参考接下来的“库的版本”)。

l 如果上叙的查找都失败,连接器就查找默认路径 /usr/lib ,如果库文件依旧没有找到,则显示一个错误然后退出。

连接器找到了库文件后,先打开它,然后读取ELF头,找到指向各个段的指针。连接器为库的代码段和数据段分配空间并映射到内存,随后是bss(不分配空间)。.通过库的 .dynamic 段,连接器添加这个库的符号表到符号表链,如果库所依赖的其它库没有装载的话,则添加那个库到装载队列中。

完成这个过程后,所有的库都已经被映射,loader在逻辑上拥有了一个全局的符号表,它是全部程序和被映射库的符号表的联合。