【Linux】动静态库

一、库

静态库 .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

  1. 在系统共享库路径下,建立同名软连接

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又有偏移量又有虚拟地址。

相关推荐
lingllllove5 分钟前
使用 HTTP::Server::Simple 实现轻量级 HTTP 服务器
服务器·网络协议·http
Linux运维老纪27 分钟前
K8s之Service详解(Detailed Explanation of K8s Service)
服务器·网络·云原生·容器·kubernetes·云计算·运维开发
程序猿编码1 小时前
自定义命令执行器:C++中命令封装的深度探索(C/C++实现)
linux·c语言·c++·网络安全·shell·命令行
神秘剑客_CN2 小时前
使用windows笔记本让服务器上网
运维·服务器·windows
vortex53 小时前
Shell基础:中括号的使用
linux·运维·bash·shell
基哥的奋斗历程3 小时前
Docker 常用命令
运维·docker·容器
HEX9CF5 小时前
【Docker】快速部署 Nacos 注册中心
运维·docker·容器
从未止步..6 小时前
Jenkins未在第一次登录后设置用户名,第二次登录不进去怎么办?
java·运维·jenkins