IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux中的库(静态库和动态库)详解 -> 正文阅读

[系统运维]Linux中的库(静态库和动态库)详解

前言

介绍Linux库之前,首先介绍下分文件,在学习或者开发中,实现一个项目需要实现很多的功能,那么这些功能不可能在一个".c"文件下实现,需要多个".c"文件来共同实现,但是程序的入口只有一个,就体现了分文件编程的重要性,在主函数中调用其余的功能函数。

分文件编程的优点及意义就是:

  • 分模块编程思想
  • 功能责任划分清晰
  • 方便调试
  • 主程序简洁

比如我要实现一个加减乘除的demo,main主功能一个文件,function函数功能一个文件,如果代码量庞大,这样分开写,优点十分明显。

calculateMain.c主功能文件
#include <stdio.h>//头文件中,带箭头表明到/usr/include/或者/usr/local/include/去找这个头文件
#include "calculate.h"//带引号是自己写的头文件,优先去本目录下找,找不到再去include/找

int main(){
        int num1;
        int num2;
        int ret;
        float fret;
        printf("请输入第一个数\n");
        scanf("%d",&num1);
        printf("请输入第二个数\n");
        scanf("%d",&num2);
        printf("结果如下:\n");
        ret = add(num1,num2);
        printf("两数之和是:%d\n",ret);
        ret = subtract(num1,num2);
        printf("两数之差是:%d\n",ret);
        fret = divide(num1,num2);
        printf("两数之商是:%.3f\n",fret);
        ret = multiply(num1,num2);
        printf("两数之积是:%d\n",ret);
        return 0;
}

calculateFunc.c函数功能文件
int add(int num1,int num2){
        return num1 + num2;
}
int subtract(int num1,int num2){
        return num1 - num2;
}
int divide(int num1,int num2){
        float ret;
        ret = num1/num2;
        return ret;
}
int multiply(int num1,int num2){
        return num1*num2;
}
calculate.h函数声明文件

int add(int num1,int num2);
int subtract(int num1,int num2);
int divide(int num1,int num2);
int multiply(int num1,int num2);

执行下面命令:

gcc calculateMain.c calculateFunc.c

生成a.out运行即可

这就是分文件编程的简单demo,当工程量大且复杂,分文件的优点就十分突出


Linux库(静态库、共享库以及动态库)理论篇请参考这位博主:https://www.cnblogs.com/sunsky303/p/7731911.html


Linux库

盗图:
在这里插入图片描述

库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容。

用户需要同时具有头文件和库。

  • 头文件(相当于说明书的作用,能够知道这个库能干嘛)
  • 制作出来的库(具体的实现,存放.c、.cpp)

优缺点

静态库:
优点:

  • 静态库被打包到应用程序中加载速度快
  • 发布程序无需提供静态库,因为已经在app中,移植方便

缺点:

  • 链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
  • 更新、部署、发布麻烦。

动态库:
优点:

  • 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存。
  • 程序升级简单,因为app里面没有库的源代码,升级之后只要库的名字不变,函数名以及参数不变,只是实现做了优化,就能加载成功。

缺点:

  • 加载速度比静态库慢
  • 发布程序需要提供依赖的动态库

静态库

静态函数库,在程序执行前(编译)就加入到目标程序中去了,那么到底怎么制作和使用呢?

静态库的制作

静态库的制作格式xxxx.a

gcc calculateFunc.c -c //生成xxx.o文件

ar rcs libcalFunc.a calculateFunc.o //xxx.o文件生成xxx.a静态库文件
静态库文件前面最好是加上lib

静态库的使用

gcc calculateMain.c -lcalFunc -L ./ -o staticFunc

-lcalFunc : -l是制定要用的动态库,库名砍头去尾(比如我原先的库名是libcalFunc.a,去掉lib和.a)
-L告诉gcc编译器从-L指定的路径去找静态库。默认是从/usr/lib /usr/local/lib去找

具体如图所示:
在这里插入图片描述

这里面的所有文件都是前言中所使用的文件。。。。。

动态库

动态函数库,是在程序执行时动态(临时)由目标程序去调用,看看怎么使用吧。。。

动态库的制作

gcc -shared -fpic calculateFunc.c -o libcalcu.so

-shared 指定生成动态库
-fpic 是标准格式,fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。

动态库的使用

动态库的使用其实和静态库是一样的语法,但是区别在怎么引用动态库,怎么指定动态库的位置

假如我们输入正确的指令:

gcc calculateMain.c -lcalcu -L ./ -o dynamicFunc

结果发现在这里插入图片描述
找不到指定位置的动态库


指定动态库位置

一般来说有三种解决方法:

  • 方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径。
    vi /etc/ld.so.conf
    添加 lib目录
    ldconfig
  • 方法二:通过环境变量LD_LIBRARY_PATH指定动态库搜索路径。

export LD_LIBRARY_PATH=”LD_LIBRARY_PATH:/opt/”

  • 方法三:在编译目标代码时指定该程序的动态库搜索路径。
    还可以在编译目标代码时指定程序的动态库搜索路径。通过gcc 的参数”-Wl,-rpath,”指定

比较常用的是方法二,这里介绍下:
和Windows里面的环境变量一样,只不过这里是命令的方法显示,输入export 命令,会显示所有的环境变量:
在这里插入图片描述
这里我们只需要将我们当前开发目录地址引入环境变量即可

命令:

export LD_LIBRARY_PATH=“/home/pi/test” //查看当前地址pwd

这样就将工作目录地址添加到环境变量了,执行就没有问题了。。

但是这样只能限制在当前会话,克隆一个或者开另一个会话就失效了
像这样,我克隆了一个会话,error了。
在这里插入图片描述


可以写一个.sh脚本,可以实现跨会话编辑。

start.sh脚本

export LD_LIBRARY_PATH="/home/pi/test"


./dynamicFunc

然后赋予脚本权限

chmod +x start.sh

tips:

chmod +x 是将文件状态改为可执行,而chmod 777 是改变文件读写权限。

运行./start.sh
在这里插入图片描述

补充

两个动态库函数重名问题
应用程序a(a.c),动态库liba.so(liba.h, liba.c),libb.so,均实现了func()

gcc -la -lb a.c

则调用的是liba.so中的函数实现

gcc -lb -la a.c

则调用的是libb.so中的函数实现

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:27:13  更:2022-06-29 19:28:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:07:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码