• 【Linux】第九章 动态库和静态库(生成原理+生成和使用+动态链接)


    🏆个人主页企鹅不叫的博客

    ​ 🌈专栏

    ⭐️ 博主码云gitee链接:代码仓库地址

    ⚡若有帮助可以【关注+点赞+收藏】,大家一起进步!

    💙系列文章💙


    【Linux】第一章环境搭建和配置

    【Linux】第二章常见指令和权限理解

    【Linux】第三章Linux环境基础开发工具使用(yum+rzsz+vim+g++和gcc+gdb+make和Makefile+进度条+git)

    【Linux】第四章 进程(冯诺依曼体系+操作系统+进程概念+PID和PPID+fork+运行状态和描述+进程优先级)

    【Linux】第五章 环境变量(概念补充+作用+命令+main三个参数+environ+getenv())

    【Linux】第六章 进程地址空间(程序在内存中存储+虚拟地址+页表+mm_struct+写实拷贝+解释fork返回值)

    【Linux】第七章 进程控制(进程创建+进程终止+进程等待+进程替换+min_shell)

    【Linux】第八章 基础IO(open+write+read+文件描述符+重定向+缓冲区+文件系统管理+软硬链接)



    💎一、动静态库原理

    源文件和头文件编程可执行程序需要进行一下四个步骤:

    1. 预处理: 完成头文件展开、去注释、宏替换、条件编译等,最终形成xxx.i文件。
    2. 编译: 完成词法分析、语法分析、语义分析、符号汇总等,检查无误后将代码翻译成汇编指令,最终形成xxx.s文件。
    3. 汇编: 将汇编指令转换成二进制指令,最终形成xxx.o文件。
    4. 链接: 将生成的各个xxx.o文件进行链接,最终形成可执行程序。

    其中,我们可以将一堆.o文件打包成库

    • 在Linux当中,以.so为后缀的是动态库,以.a为后缀的是静态库。
    • 在Windows当中,以.dll为后缀的是动态库,以.lib为后缀的是静态库。

    💎二、静态库

    🏆1.特点

    静态库(.a)是程序在编译链接的时候把库的代码拷贝到可执行文件当中的,生成的可执行程序在运行的时候将不再需要静态库。使用静态库生成的可执行程序会比一般程序大,同时也会占用大量的空间

    🏆2.生成

    示例生成一下四个代码,两个源文件,add.c和sub.c两个头文件add.h和sub.h

    add.c

    #include "add.h"
    int add(int a, int b)
    {
    	return a + b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    add.h

    #pragma once
    
    extern int add(int a, int b);
    
    • 1
    • 2
    • 3

    sub.c

    #include "sub.h"
    int sub(int a, int b)
    {
    	return a - b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    sub.h

    #pragma once
    
    extern int sub(int a, int b);
    
    • 1
    • 2
    • 3

    生成.o文件并且打包

    libcal.a:add.o sub.o
    	ar -rc libcal.a add.o sub.o
    sub.o:sub.c
    	gcc -c sub.c -o sub.o -std=c99//编译器版本低的话要加上这个,否则不用
    add.o:add.c
    	gcc -c add.c -o add.o
    
    .PHONY:clean
    clean:
    	rm -f *.o *.a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    gcc -c mymath.c -o mymath.o:-c,生成.o文件,-o,重命名为mymath.o,可以简写为gcc -c mymath.c

    ar -rc libmymath.a mymath.o myprint.o:ar命令是gnu的归档工具,常用于将目标文件打包为静态库,-r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件,-c(create):建立静态库文件

    发布静态库

    发布静态库有两个文件夹,include存放头文件合集,lib存放库合集

    libcal.a:add.o sub.o
    	ar -rc libcal.a add.o sub.o
    sub.o:sub.c
    	gcc -c sub.c -o sub.o -std=c99//编译器版本低的话要加上这个
    add.o:add.c
    	gcc -c add.c -o add.o
    
    .PHONY:static//打包
    static:
    	mkdir -p staticlib/lib 
    	mkdir -p staticlib/include
    	cp *.a staticlib/lib 
    	cp *.h staticlib/include
    
    .PHONY:clean
    clean:
    	rm -f *.o *.a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    mkdir -p staticlib/ lib 创建一个路径staticlib/ lib
    mkdir -p staticlib/ include 创建一个路径staticlib/ include
    cp *.a staticlib/lib 把所有.a库文件拷贝进 lib路径下
    cp *.h staticlib/ include 把所有.h头文件拷贝进第 include路径下

    .PHONY:static//打包 make static将所有文件组织起来

    🏆3.使用

    • ” ”:在当前路径下查找头文件
    • < > :在系统头文件路径下查找头文件

    方法一:指定路径头文件搜索路径

    • -I:指定头文件搜索路径。
    • -L:指定库文件搜索路径。
    • -l:指明需要链接库文件路径下的哪一个库。

    -I+你的头文件搜索路径(-l是include缩写,意为头文件) ,-L+你的库路径 即可(-L是link缩写,意为库),-l库名 (-l库名之间尽量不带空格)

    gcc main.c -o main -I ./staticlib/include/ -L ./staticlib/lib/ -lcal
    
    • 1

    编译器不知道你所包含的头文件add.h在哪里,所以需要指定头文件的搜索路径,头文件add.h当中只有add函数的声明,并没有该函数的定义,所以还需要指定所要链接库文件的搜索路径,需要指明需要链接库文件路径下的哪一个库(库文件名去掉前缀lib,再去掉后缀.so或者.a),-I-L-l这三个选项后面可以加空格,也可以不加空格

    方法二:将头文件和库文件拷贝到系统路径下(不推荐)

    我们生成的库名叫,libcal.a去掉前称和后缀就是cal

    将头文件和库文件拷贝到系统路径下

    sudo cp staticlib/include/* /usr/include/
    sudo cp staticlib/lib/libcal.a /lib64/
    
    • 1
    • 2

    链接库时,指定使用的库,cal为去掉前称和后缀

    gcc main.c -lcal
    
    • 1

    💎三、动态库

    🏆1.特点

    动态库(.so)是程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。(即:动态库链接的可执行程序中如果调用外部函数时,程序里面只有函数的地址,函数的具体实现还在库中)动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。

    🏆2.生成

    • shared: 表示生成共享库格式,动态库打包的时候需要加上
    • fPIC:产生位置无关码,源文件编译成.o文件需要加上

    生成,so文件并且打包

    libcal.so:add.o sub.o
    	gcc -shared -o libcal.so add.o sub.o
    add.o:add.c
    	gcc -fPIC -c add.c -o add.o -std=c99
    sub.o:sub.c
    	gcc -fPIC -c sub.c -o sub.o
    
    .PHONY:clean
    clean:
    	rm -rf *.o *.so
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    gcc -shared -o libcal.so add.o sub.o:生成动态库,需要在前面加上-shared

    gcc -fPIC -c sub.c -o sub.o:生成.o文件需要在前面加上-fPIC

    发布动态库

    libcal.so:add.o sub.o
    	gcc -shared -o libcal.so add.o sub.o
    add.o:add.c
    	gcc -fPIC -c add.c -o add.o -std=c99
    sub.o:sub.c
    	gcc -fPIC -c sub.c -o sub.o
    
    .PHONY:dyl//打包
    dyl:make
    	mkdir -p dyllib/lib 
    	mkdir -p dyllib/include
    	cp *.so dyllib/lib 
    	cp *.h dyllib/include
    
    .PHONY:clean
    clean:
    	rm -rf *.o *.so
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    mkdir -p dyllib/ lib 创建一个路径dyllib/ lib
    mkdir -p dyllib/ include 创建一个路径dyllib/ include
    cp *.a dyllib/lib 把所有.a库文件拷贝进 lib路径下
    cp *.h dyllib/ include 把所有.h头文件拷贝进第 include路径下

    .PHONY:dyl//打包 make dyl将所有文件组织起来

    🏆3.使用

    指定路径头文件搜索路径:

    -I+你的头文件搜索路径(-l是include缩写,意为头文件) ,-L+你的库路径 即可(-L是link缩写,意为库),-l库名 (-l库名之间尽量不带空格)

    gcc main.c -o main -I ./dyllib/include/ -L ./dyllib/lib/ -lcal
    
    • 1

    与静态库的使用不同的是,此时我们生成的可执行程序并不能直接运行,必须让进程找到动态库

    [Jungle@VM-20-8-centos:~/lesson24]$ ldd a.out
         linux-vdso.so.1 =>  (0x00007ffe091a7000)
         libcal.so => not found
         libc.so.6 => /lib64/libc.so.6 (0x00007f6a85fae000)
         /lib64/ld-linux-x86-64.so.2 (0x00007f6a8657e000)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    动态库拷贝到系统路径干力1ib64-- 安装(不推荐)

    更改LD_LIBRARY_PATH

    LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径,我们只需将动态库所在的目录路径添加到LD_LIBRARY_PATH环境变量当中即可

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/Jungle/lesson24/dyllib/lib
    
    • 1

    重启xshell就还原了

    系统配置文件

    /etc/ld.so.conf.d/路径下存放的全部都是以.conf为后缀的配置文件,而这些配置文件当中存放的都是路径,系统会自动在/etc/ld.so.conf.d/路径下找所有配置文件里面的路径,之后就会在每个路径下查找你所需要的库。

    在库路径下创建创建自己的配置文件

    sudo touch /etc/ld.so.conf.d/dyl.conf
    
    • 1

    将路径写入配置文件

    sudo vim /etc/ld.so.conf.d/dyl.conf
    
    • 1

    以下是写入内容

    /home/Jungle/lesson24/dyllib/lib/
    
    • 1

    刷新配置文件

    sudo ldconfig
    
    • 1

    删除系统配置文件

    sudo rm /etc/ld.so.conf.d/dyl.conf
    
    • 1

    🏆4.动态链接

    动态库是程序在运行的时候才去链接相应的动态库代码的,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表。在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)

    在这里插入图片描述


  • 相关阅读:
    Mac怎么清理磁盘空间?释放Mac磁盘空间有效方法
    【Spring传播机制底层原理】
    java多线程基础——Callable接口及线程池补充
    Android 小部件播放视频
    了解低压差稳压IC(LDO)及其在电池驱动设备中的意义
    饥荒联机版 Don‘t Starve Together服务器架设
    短视频源码php
    Python入门自学进阶-Web框架——25、DjangoAdmin项目应用-分页与过滤
    YARN功能介绍、交互流程及调度策略
    linux学习实操计划0101-linux卸载软件
  • 原文地址:https://blog.csdn.net/YQ20210216/article/details/127656944