一、库
静态库 .a[Linux]、.lib[windows]
动态库 .so[Linux]、.dll[windows]
二、静态库使用
如果我们要做一个静态库的话,首先我们需要把我们源文件(.c/.cpp)隐藏起来,头文件(.h)必须暴露出来,
1.我们先要把我们所有的.c文件编译成.o文件,因为我们都知道我们正常进行程序翻译的时候,首先要做的工作就是把.c变成.o文件,最后把所有.o都链接起来。
[zxw@hcss-ecs-cc58 lesson20]$ ll
total 24
-rw-rw-r-- 1 zxw zxw 1350 Jan 20 22:14 my_stdio.c
-rw-rw-r-- 1 zxw zxw 408 Jan 20 20:01 my_stdio.h
-rw-rw-r-- 1 zxw zxw 2784 Jan 26 19:42 my_stdio.o
-rw-rw-r-- 1 zxw zxw 156 Jan 26 19:40 my_string.c
-rw-rw-r-- 1 zxw zxw 43 Jan 26 19:40 my_string.h
-rw-rw-r-- 1 zxw zxw 1272 Jan 26 19:42 my_string.o
[zxw@hcss-ecs-cc58 lesson20]$ ar -rc libmystdio.a my_stdio.o my_string.o
2.把所以.o文件打包
指令:ar -rc(-r是replace,-c是create)
静态库必须有前缀lib,后缀.a。
2.1 安装系统
这个库制作好了,直接把他安装到系统里面:
把我们头文件拷贝到系统特定路径里,Linux系统里默认搜索头文件路径是/usr/include
[zxw@hcss-ecs-cc58 lesson20]$ sudo cp *.h /usr/include/
然后把我们库也要安装到系统里,默认路径一般是/lib64/
[zxw@hcss-ecs-cc58 lesson20]$ sudo cp libmystdio.a /lib64/
之后我们就可以使用我们的头文件了。
#include<my_stdio.h>
#include<my_string.h>
#include<stdio.h>
int main()
{
const char *a = "abcdf";
printf("%s: %d\n",a,my_strlen(a));
mFILE *fp =mfopen("./log.txt","a");
if(fp ==NULL) return 1;
mfwrite(a,my_strlen(a),fp);
mfwrite(a,my_strlen(a),fp);
mfwrite(a,my_strlen(a),fp);
mfclose(fp);
return 0;
}
[zxw@hcss-ecs-cc58 lesson20]$ gcc main.c -l mystdio
[zxw@hcss-ecs-cc58 lesson20]$ ll
total 52
-rwxrwxr-x 1 zxw zxw 8896 Jan 27 12:39 a.out
在这里我们要在gcc main.c后面添加-l mystdio --->那是因为gcc是编C语言的,他默认要认识C标准库的,我们刚才写的库叫第三方库要让编译器认识所以我们要在后面-l(link) 链接mystdio这个静态库
2.2 在当前路径下进行开发
[zxw@hcss-ecs-cc58 other_people]$ ll
total 20
-rw-rw-r-- 1 zxw zxw 4310 Jan 27 13:05 libmystdio.a
-rw-rw-r-- 1 zxw zxw 339 Jan 27 13:05 main.c
-rw-rw-r-- 1 zxw zxw 408 Jan 27 13:05 my_stdio.h
-rw-rw-r-- 1 zxw zxw 43 Jan 27 13:05 my_string.h
[zxw@hcss-ecs-cc58 other_people]$ gcc main.c -o main -L. -lmystdio
[zxw@hcss-ecs-cc58 other_people]$ ll
total 32
-rw-rw-r-- 1 zxw zxw 4310 Jan 27 13:05 libmystdio.a
-rwxrwxr-x 1 zxw zxw 8896 Jan 27 13:15 main
-rw-rw-r-- 1 zxw zxw 342 Jan 27 13:06 main.c
-rw-rw-r-- 1 zxw zxw 408 Jan 27 13:05 my_stdio.h
-rw-rw-r-- 1 zxw zxw 43 Jan 27 13:05 my_string.h
指令:gcc main.c -o main -L. -lmystdio
-L.:-L选项用于指定库文件的搜索路径。这里的.表示当前目录,即告诉编译器在当前目录下搜索库文件。
2.3 带路径的库
Makefile ----> 先发布库
libmystdio.a:my_stdio.o my_string.o
ar -rc $@ $^
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -rf *.a *.o stdc.*
.PHONY:output
output:
mkdir -p stdc/include
mkdir -p stdc/lib
cp -f *.h stdc/include
cp -f *.o stdc/lib
tar -czf stdc.tgz stdc
使用带路径的库
[zxw@hcss-ecs-cc58 lesson20]$ ll
total 12
-rw-rw-r-- 1 zxw zxw 339 Jan 27 12:21 main.c
drwxrwxr-x 3 zxw zxw 4096 Jan 27 14:09 other_people
-rw-rw-r-- 1 zxw zxw 1696 Jan 27 14:11 stdc.tgz
[zxw@hcss-ecs-cc58 lesson20]$ tar xzf stdc.tgz
[zxw@hcss-ecs-cc58 lesson20]$ ll
total 16
-rw-rw-r-- 1 zxw zxw 339 Jan 27 12:21 main.c
drwxrwxr-x 3 zxw zxw 4096 Jan 27 14:09 other_people
drwxrwxr-x 4 zxw zxw 4096 Jan 27 13:48 stdc
-rw-rw-r-- 1 zxw zxw 1696 Jan 27 14:11 stdc.tgz
[zxw@hcss-ecs-cc58 lesson20]$ gcc main.c -I stdc/include/ -L stdc/lib/ -l mystdio
-I(大写的 i)选项用于指定头文件的搜索路径。这里告诉编译器在stdc/include目录下搜索main.c中#include指令所包含的头文件。
三、动态库使用
3.1 安装到系统
Makefile
libmystdio.so:my_stdio.o my_string.o
gcc -o $@ $^ -shared
%.o:%.c
gcc -fPIC -c $<
.PHONY:clean
clean:
rm -rf *.a *.so *.o
[zxw@hcss-ecs-cc58 other_people]$ make
gcc -fPIC -c my_stdio.c
gcc -fPIC -c my_string.c
gcc -o libmystdio.so my_stdio.o my_string.o -shared
shared:表示⽣成共享库格式
fPIC:产⽣位置⽆关码(position independent code)
先拷贝到系统中,拷贝.h和拷贝到地址静态库中.h的位置一样,拷贝.so和拷贝和拷贝到地址静态库中.o的位置一样
[zxw@hcss-ecs-cc58 other_people]$ gcc main.c -l mystdio
[zxw@hcss-ecs-cc58 other_people]$ ll
total 36
-rwxrwxr-x 1 zxw zxw 8520 Jan 27 14:38 a.out
[zxw@hcss-ecs-cc58 other_people]$ ./a.out
abcdf: 5
[zxw@hcss-ecs-cc58 other_people]$ ldd a.out
linux-vdso.so.1 => (0x00007fff17feb000)
libmystdio.so => /lib64/libmystdio.so (0x00007f41fc1bc000)
libc.so.6 => /lib64/libc.so.6 (0x00007f41fbdee000)
/lib64/ld-linux-x86-64.so.2 (0x00007f41fc3be000)
我们在ldd a.out这个文件时,可以看清 libmystdio.so => /lib64/libmystdio.so(0x00007f41fc1bc000)
可以看到库的名称和库的完整路径以及库的地址
当我们把库的删除掉还有头文件。
[zxw@hcss-ecs-cc58 other_people]$ ./a.out
./a.out: error while loading shared libraries: libmystdio.so: cannot open shared object file: No such file or directory
[zxw@hcss-ecs-cc58 other_people]$ ldd a.out
linux-vdso.so.1 => (0x00007ffc86fbd000)
libmystdio.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f94ec189000)
/lib64/ld-linux-x86-64.so.2 (0x00007f94ec557000)
结果就是我们执行不了文件与静态库的不一样。
3.2 在当前路径下进行开发
动态库在当前路径进行开发与静态库在当前路径进行开发执行的指令一样。
3.3 带路径的库
[zxw@hcss-ecs-cc58 other_people]$ ll
-rw-rw-r-- 1 zxw zxw 339 Jan 27 19:23 main.c
drwxrwxr-x 4 zxw zxw 4096 Jan 27 19:23 stdc
//用静态链接的方式
[zxw@hcss-ecs-cc58 other_people]$ gcc main.c -o main -I stdc/include/ -L stdc/lib/ -l mystdio
//运行之后静态库的方法发生了变化
[zxw@hcss-ecs-cc58 other_people]$ ./main
./main: error while loading shared libraries: libmystdio.so: cannot open shared object file: No such file or directory
[zxw@hcss-ecs-cc58 other_people]$ ldd main
linux-vdso.so.1 => (0x00007fff5fb4e000)
libmystdio.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f3b8de67000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b8e235000)
接下来要给系统指定路径,查找自己的动态库-->方法
1.拷贝.so到系统默认路径下,比如/lib64
- 在系统共享库路径下,建立同名软连接
3.Linux系统中,把路径添加到系统当中,LD_LIBRARY_PATH
LD_LIBRARY_PATH=$LD_LIBRART_PATH:/home/zxw/linux/112/lesson20/other_people/stdc/lib/
4
[zxw@hcss-ecs-cc58 other_people]$ sudo touch /etc/ld.so.conf.d/112.conf
[zxw@hcss-ecs-cc58 other_people]$ ll /etc/ld.so.conf.d/
total 16
-rw-r--r-- 1 root root 0 Jan 27 20:13 112.conf
[zxw@hcss-ecs-cc58 lib]$ sudo vim /etc/ld.so.conf.d/112.conf
112.conf
/home/zxw/linux/112/lesson20/other_people/stdc/lib
指令执行:
sudo ldconfig
四、可执行程序(ELF)格式
[zxw@hcss-ecs-cc58 lesson20]$ size a.out
text data bss dec hex filename
2709 596 4 3309 ced a.out
最常见的节:
• 代码节(.text):用于保存机器指令,是程序的主要执行部分。
• 数据节(.data):保存已初始化的全局变量和局部静态变量。
可执行程序和动态库以及汇编形成的.o文件都是ELF格式。
所谓的链接就是将我们一个个的相同属性的section进行合并。
Program Header
Section header table
https://blog.csdn.net/daide2012/article/details/73065204?fromshare=blogdetail&sharetype=blogdetail&sharerId=73065204&sharerefer=PC&sharesource=m0_73911405&sharefrom=from_linkELF HEADER主要⽬的是定位⽂件的其他部分。
Section Header Table在链接时起作用,Program Header Table⼀个在运⾏加载时起作用,我们看内部信息也能看出Program Header Table又有偏移量又有虚拟地址。