分类:
2009-06-02 16:07:19
头文件相关
一 linux的头文件如放在/usr/include 中 ,
这是起标准存放头文件的堤防
在原始文件.c中就可通过 #include <>方式应用
二 头文件放在任意目录中,非/usr/include 中
在原始.c文件中,必需通国#include " "方式引用
在gcc中必需需要 -I的参数来指定头文件的位置比如
gcc -I/usr/local/include a.c (a.c应用了 #include "bb.h");表示在/usr/local/include下找bb.h
三 怎样在configure 或makefile指定头文件的位置
有时候,软件编译的时候需要某些头文件,但这些头文件并没在/usr/include 中,或configure, makefile里面的指定的目录中,
那么这个时候怎么办?
第1种办法是把头文件放到标准目录中,第2种办法是把这些头文件的位置写如configure或makefile中
库总结
一 linux库的分类
linux库分为静态库和共享库两种类型.前者在程序编译的时候就被包含进程序,因此程序本身比较大.但是加载程序运行时候起动速度快.后者在程序编译的时候没有包含进程序,只在程序里面留下调用库中内容 (函数 变量)的符号,程序本身比较小,但是在加载程序运行的时候启动速度没有前者使用静态库的程序的加载速度快,还有个区别在于如果库发声改变,那么静态库的程序必需要从新编译,才能使用新库的功能,否则只能使用旧库的功能
二 库的命名
库的文件名在linux中必须符合一定的国际标准
(一)静态库的命名
其文件名为 lib+库名+.a
比如说 libmysql.a等
(二)共享库的命名
1,在新系统中(kenrel > 2.2.x??)
一个动态库必需包含3个文件.其中第1个文件是第2个文件的连接,第2个文件是真实的第3个文件的符号连接.
这样做,是为了库的升级管理方便
格式如下:
第1个文件名字为: lib+库名+.so 标准叫 linkname(连名)
第2个文件名字为: lib+库名+.so+.主版本号 标准叫 soname(搜名)
第3个文件名子为: lib+库名+.so+.主版本号+.子版本号(+.patch号) 标准叫 realname(实名)
比如: libmysql.so---->libmysql.so.1-->libmysql.so.1.1
这样程序只连接libmysql.so,如果 libmysql这个库发生变化,比如升级等.这需要修改 libmysql后,然后把名子比如改为
libmysql.so.1.5,然后再执行 ln libmysql.so.1.5 libmysql.so.1就可以了.当然如果 主版本号也发生变化,就执行
ln -s libmysql.so.2.0 libmysql.so.2
ln -s libmysql.so.2 libmysql.so
就完成,可以看出程序并不需要从新再编译一次.
2,在就系统中(kernel <= 2.2.x??)
形式和上面一样,但是 so 为 sa,比如
libmysql.sa---->libmysql.sa.1---->libmysql.sa.1.0
三 库的创建
(一)静态库的创建
1.创建目标文件
gcc -c a.c -o a.o
2.把目标文件合成静态库
ar rcs libs.a a.o b.o
(二)动态库的创建
1.创建目标文件
gcc -fPIC -c a.c -o a.o ;主意:这里gcc参数必需使用-fPIC或 -fpic
2.使用gcc -share -Wl, -soname, soname -o realname 目标文件 (library) 把目标文件合成共享库
gcc -shear -Wl, -soname my.so.1 -o my.so.1.0.0 a.o -lc ;这里的soname,realname不带lib,library表示要连接其他的库
执行这条语句,系统自动创建 libmy.so, libmy.so.1 libmy.so.1.0.0,当然libmy.so,libmy.so.1是libmy.so.so.1.0.0的连接
当然也可一步完成
gcc -shared -fpic -o libmy.so.1.1 a.o
主意:执行这条语句后,必需人为的执行
ln libmy.so.1.1 libmy.so.1
ln libmy.so.1 libmy.so
四 库的编译连接
库的编译连接符合以下步骤
1. 看是否通过绝对路径的方式连接库,如果否,就执行第2步
2. 由于共享库比静态库有许多优点,gcc默认情况下连接共享库,在没有找到共享库的情况下,在在相同目录下着同名的静态库
除了通过绝对路径的方式连接库外,必需使用-l参数,如果同时指定-WI,-BStatic表示指明连接静态库,-WI,-BDynameic表示指明连接
共享库, 如果同时指定-L表示在指定目录下找库
比如:
gcc test.c -lmy_1 \
-WI,-BStatic -lmy_2 \
-WI,-Bdynameic -lmy_3 \
-L/usr/local/lib -lmy_4 \
libfoo.a \
/usr/libfoo.so \
_L/usr/local/lib -WI,-BStatic -lmy_5\
对于my_1
先在 /lib下,找是否存在libmy_1.so,如果没有,在找 libmy_1.a,如果没有,就到
/usr/lib下执行相通不奏 ,如果都没找到,就返回错误
对于my_2
指定找libmy_2.a,当然现在/lib后在/usr/lib下找,如果没有,返回错误
对于my_3
指定找libmy_2.so,先在/lib后在/usr/lib,如果没有,返回,错误
对于my_4
指定在目录下/usr/local/lib,现找libmy_4.so 再找 libmy_4.a如果没有,返回错误
对于libfoo.a
指定在当前目录下找libfoo.a,如果没有,返回错误
对于libfoo.so
指定在/usr目录下找libfoo.so,如果没有,返回错误
对于my_5
指定在/usr/local/lib 找libmy_5.a,如果煤油找到,返回错误
五 库的加载
(一)静态库的加载
无,因为静态库被打包进程序,程序运行时无须加载库
(二)共享库的加载
1,程序运行时候加载
按一下规则找到最先的库进行加载
(1)如果编译连接共享库的时候,gcc用-WL,-rpath参数,就把这个库的位置已经打包进程序,应此从指定的位置加载即可,
如果加载错误,就执行2(???未实验过)
(2)如果设置了LD_LIBRARY_PATH,那么就从这指定的位置加载库,如果失败,就执行3
这是在处理非管理员用户加载程序运行的时候,而程序所需要的库没有放在(1),(3),(4),(5)所在的位置的时候,通过设置LD_LIBRARY_PATH变量来解决
(3)从/etc/ld.so.cache中的指定目录加载库,如果失败,就执行4
(4)从/lib中加载库,如果失败执行5
(5)从/usr/lib中加载库,如果失败就返回错误
2,按需加载(就是动态库加载)
主意:这里的动态库,不是库的类型,而是一种共享库的加载技术,就是程序运行时候不加载共享库,当需要时候在加载库.而是执行
dlopen,方式来加载共享库的,加载库的顺序和上面1的方式相同
六 库的操作
(一) ldd
用于查看一个程序或库引用了哪些库
(二) ldconfig
就是来操作 /etc/ld.so.cache的,由于其内容无法直接操作,就通过先把目录位置
放在/etc/ld.so.conf,然后执行ldconfig,/etc/ld.so.conf的内容就会更新到/etc/ld.so.cache中.
这条命令用于:当把共享库放在其他位置(不是/lib 或/usr/lib),比如/usr/local/lib中,然后把
/usr/local/lib放在/etc/ld.so.conf中,执行 ldconfig后,所有需要这些库的程序就能被成功加载,具体情看上面 程序运行时加载库
(三) nm
用于看一个库有哪些函数.如果表示U的函数,表明这个库使用这个函数,但是这个函数没有在这个库中定义,说明这个库是引用其他库的函数,如果表示T的函数,就表示这个函数就在这个库中定义,实现.
七 其他主意
(一) 编译连接目标文件和编译连接静态库的区别
gcc test.c a.o
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/vpxiroot/archive/2009/05/11/4167399.aspx