文章目录
1,共享库的创建
a,编写库源码hello.c,bye.c
linux@linux:~/test/stdio/share_library$ vi hello.c
#include <stdio.h>
void hello(void)
{
printf("hello world\n");
return ;
}
linux@linux:~/test/stdio/share_library$ vi bye.c
#include <stdio.h>
void bye(void)
{
printf("bye!\n");
return ;
}
b,为共享库编写头文件common.h
#ifndef __COMMON_H__
#define __COMMON_H__
void hello(void);
void bye(void);
#endif
c,编译生成目标文件
linux@linux:~/test/stdio/share_library$ gcc -c hello.c bye.c -fPIC -Wall
linux@linux:~/test/stdio/share_library$ ls
bye.c bye.o common.h hello.c hello.o
- -fPIC选项:告诉编译器生成位置无关代码
- 位置无关代码:生成的".o文件"文件中的代码可以被加载到任意的地址执行。编译的时候用到了相对寻址而不是绝对寻址
d,创建共享库common
linux@linux:~/test/stdio/share_library$ gcc -shared hello.o bye.o -o libcommon.so.1
linux@linux:~/test/stdio/share_library$ ls
bye.c bye.o common.h hello.c hello.o libcommon.so.1
- -shared选项:告诉编译器生成一个共享库
- 生成的共享库的文件名叫"libcommon.so.1",其中".so"表示这是一个共享库,".1"表示这个库的版本是1
e,为共享库文件创建链接文件
linux@linux:~/test/stdio/share_library$ ln -s libcommon.so.1 libcommon.so
linux@linux:~/test/stdio/share_library$ ll
total 36
drwxr-xr-x 2 linux linux 4096 11月 5 19:53 ./
drwxrwxr-x 5 linux linux 4096 11月 5 19:09 ../
-rw-rw-r-- 1 linux linux 70 11月 5 19:13 bye.c
-rw-rw-r-- 1 linux linux 1312 11月 5 19:38 bye.o
-rw-rw-r-- 1 linux linux 86 11月 5 19:24 common.h
-rw-r--r-- 1 linux linux 78 11月 5 19:29 hello.c
-rw-rw-r-- 1 linux linux 1324 11月 5 19:38 hello.o
lrwxrwxrwx 1 linux linux 14 11月 5 19:53 libcommon.so -> libcommon.so.1*
-rwxrwxr-x 1 linux linux 6937 11月 5 19:51 libcommon.so.1*
2,共享库的使用
a,编写测试程序test.c
#include <stdio.h>
#include "common.h"
int main(int argc, const char *argv[])
{
hello();
bye();
return 0;
}
b,编译test.c并链接共享库libcommon.so
linux@linux:~/test/stdio/share_library$ gcc test.c -o test.out -L. -lcommon
linux@linux:~/test/stdio/share_library$ ls
bye.c bye.o common.h hello.c hello.o libcommon.so libcommon.so.1 test.c test.out
linux@linux:~/test/stdio/share_library$ ./test.out
./test.out: error while loading shared libraries: libcommon.so: cannot open shared object file: No such file or directory
- “gcc test.c -o test.out -L. -lcommon”,可以发现此处共享库和静态库用法相同;GCC在链接时首先找共享库,如果共享库不存在,则链接静态库,如果静态库也找不到,则报错;加"-static"选项后,编译器会直接去找静态库。
- 执行时出错原因:因为程序链接的是共享库,并没有复制共享库中的代码,程序在执行时还会去加载用到的共享库,在加载的时候回去缺省的路径(比如"/lib","/usr/lib")下去寻找共享库,但是我们创建的库在当前目录下,并不在系统库的搜索路径里,所以在执行的时候找不到共享库就报错了;
- 创建好共享库后还需要添加共享库加载路径
3,添加共享库的加载路径
a,在LD_LIBRARY_PATH环境变量中库所在路径
linux@linux:~/test/stdio/share_library$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
linux@linux:~/test/stdio/share_library$ ./test.out
hello world
bye!
- export:将原来的环境变量导出
- “:“前面”$LD_LIBRARY_PATH"是引用原先的值;”:“后面的”.“是追加了当前目录;还可以追加其余共享库的路径,要用”:"隔开
- 此方法是临时的,只对当前终端有效。当重新打开一个终端再执行改程序时又会报错
b,把库拷贝到/usr/lib和/lib目录下
- 不建议采用这种方案,拷贝到该目录下需要管理员权限
- 一般系统库放在该目录下,程序员开发的库放在其他目录下更加合适
c,添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新
- 在/etc/ld.so.conf.d/目录下创建my_common.conf文件
linux@linux:~/test/stdio/share_library$ sudo vi /etc/ld.so.conf.d/my_common.conf
[sudo] password for linux:
- 文件中写入共享库路径
/home/linux/test/stdio/share_library
- 使用ldconfig刷新
linux@linux:~/test/stdio/share_library$ sudo ldconfig
ldconfig会读取这个目录下面所有的配置文件,把配置文件路径中的库的所有信息提取出来
- 在多个终端都可执行测试程序
linux@linux:~/test/stdio/share_library$ ./test.out
hello world
bye!