[Linux高级编程]工具&库

来源:互联网 发布:mysql 默认 编辑:程序博客网 时间:2024/04/26 12:56

1 gcc基本命令

    -o  输出文件名
            -O  -O0 -O1 -O2 -O3     编译优化
            -g  -g0 -g1 -g2 -g3         产生调试信息
            -W  all  error    
            -Wall                              显示所有警告   
            -Werror                          把警告当错误
            -w                                  关闭警告   
            -c                                   只编译不连接
            -E                                   预编译
            -S                                   汇编
            -D                                   在命令行定义宏。

#include<stdio.h>int main(){  printf("NUM = %d\n",NUM);  return 0;}

                      
           -x  指定编译的语言类型 c++ /c /.S /none 自动判定
           -std=C89 /C99

编译过程:-E  -c -S   自动调用连接器 ,连接器 ld

补充文件名后缀:.a  静态库  .so 动态库  .i 预编译文件


2 静态库的编译与使用

2.1 静态库

函数等代码封装的二进制已经编译的归档文件
采用库的方式管理代码优点:1 容易组织代码 2 复用 3保护代码版权
静态库的静态的含义: 编译好的程序运行的时候不依赖库。库作为程序的一部分编译连接。 静态库本质:就是目标文件集合(归档)


2.2 静态库的编译及使用

编译成目标文件 gcc -c -static 代码文件.c( -static  可选)

cc -c  inputInt.c graphic.c
归档成静态库   ar -r 静态库文件  被归档的文件                 ar相关参数
ar -r libdemo1.a inputInt.o graphic.o//提示完成ar: creating libdemo1.a
察看函数符号表 nm 静态库或者动态库或者目标文件或者执行文件
 nm libdemo1.a//显示函数表 inputInt.o:00000000 T inputInt         U __isoc99_scanf         U printfgraphic.o:00000000 T graphic         U putchar
使用静态库       gcc 代码  静态库
 cc main.c -ldemo1 -L.

注意:

库命名规则: (1) lib库名.a  (2)lib库名.a.主版本号.副版本号.批号
库使用规则: -l 库名  -L 库所在目录                
                                   

3 动态库的编译与使用    

3.1 动态库(共享库)

动态库是可以执行,静态库不能执行 ,但动态库没有main,不能独立执行。 动态库不会连接成程序的一部分。 程序执行的时候,必须需要动态库文件。

 

ldd  察看程序需要调用的动态库 (ldd 只能察看可执行文件). 


readelf -h 察看执行程序头.


3.2 动态库的编译及使用

编译  gcc -c -fpic(可选)  源码文件

 gcc -c graphic.c  inputInt.c -std=c99

连接  gcc -shared  -o动态库文件名   目标文件名

gcc -shared -olibdemo2.so graphic.o inputInt.o


也可一步完成

gcc  -fpic   -shared graphic.c  inputInt.c  -olibtiger.so
使用动态库

gcc 代码    动态库文件名  
gcc 代码   -l库名 -L动态库所在路径


cc -omain main.c -ldemo2 -L.

但是程序运行会提示以下错误:

main: error while loading shared libraries: libdemo2.so: cannot open shared object file: No such file or directory

这是因为程序运行时没有找到动态链接库造成的。


关于动态库的加载:1.找到动态库 2.加载动态库到内存 3.映射到用户的内存空间

系统对动态库查找规则: /lib  /usr/lib 到环境变量LD_LIBRARY_PATH指定的路径中查找
缓冲机制: 把/lib:/usr/lib:LD_LIBRARY_PATH加载到缓冲。
                  /sbin/ldconfig -v 刷新缓冲中so的搜索数据


使用以下方法可以解决此问题

a. 在linux下最方便的解决方案是拷贝libtiger.so到绝对目录 /lib 下(但是,要是超级用户才可以,因此要使用sudo哦,亲)。就可以生成可执行程序了

b.第二种方法是:将动态链接库的目录放到程序搜索路径中,可以将库的路径加到环境变量LD_LIBRARY_PATH中实现:

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH


4 libdl.so 动态加载

上面的方法是在编译时链接,运行时加载的库方法。使用dl接口显式地加载,不需要链接编译。动态库中函数的查找已经封装成库libdl.so


源代码中包含<dlfcn.h>  编译时加入库-ldl 具体方法:
加载
void *dlopen(const char *filename, int flag);
参数:filename, 如果不是绝对路径,那么会从如下路径查找,$LD_LIBRARY_PATH, /etc/ld.so.cache, /usr/lib, /lib.
         flag,     

RTLD_LAZY 符号在被调用时解析 RTLD_NOW 符号在函数dlopen返回前被解析 RTLD_GLOBAL 会导出所有符号,就像它们被直接链接一样 返回值:如果找到filename返回句柄,否则NULL

使用     

void *dlsym(void *handle, char *symbol);
dlsym在加载的对象(由handle所指的共享对象)中搜索在symbol中命名的符号或函数。
dlsym返回指向符号的指针,有错则返回NULL

*检查错误
contst char *dlerror(void);

*卸载共享对象
int dlclose(void *handle);
dlclose卸载handle所指的共享对象。同时使得handle无效。
由于dl库维护着动态库的链接数,只有在dlclose对一个动态库的调用次数等于dlopen时,他们占用的资源才释放。

注意:编译时候要加入 -ldl (指定dl库)

#include<dlfcn.h>#include<stdio.h>#include<stdlib.h>int main(){  void *f1 = dlopen("./libdemo2.so",RTLD_LAZY);  if(!f1)   {printf("动态库打开失败!\n");return 0;  }  void (*f2)(int) = dlsym(f1,"graphic");  if(!f2)  {printf("函数加载失败:%s\n",dlerror());return(EXIT_FAILURE);  }  f2(5);  dlclose(f1);    return 0;}


0 0
原创粉丝点击