静态库和共享库

news2024/11/13 11:26:08

文章目录

    • 库的概念
    • 函数库
    • 库函数
    • 静态库的创建与使用
      • 静态库的概念
      • 静态库的创建
      • 代码示例--静态库的创建和使用
    • 共享库的创建和是使用
      • 共享库的概念
      • 共享库的创建
      • 共享库的使用
    • 总结

库的概念

当进行编辑C代码的时候常常会用到printf函数,这个函数被声明在stdio.h头文件中。这里需要注意的是声明和定义是两个不同的概念:**定义是指为变量、函数或结构体等分配内存空间并初始化的过程。声明:声明是指告诉编译器某个变量、函数或结构体的类型和名称,但不分配内存空间。声明通常只包含类型和名称,不包含初始值。**例如在stdio.h头文件中的printf函数的声明如下:

image-20240830105029085

可以看到在stdio.h中并没有printf函数具体的实现方法,printf函数的实现在/usr/lib目录下的一个后缀名为.so的文件里,也就是说函数的具体实现方法对我们而言是不可见的,头文件仅仅是给我们用户提供一个调用接口供用户使用。而在实际使用中,内核已经帮我们去实现了这两者间的映射关系,所以能够通过直接包含头文件就能够使用它里边的函数。

函数库

  • 函数库是由系统建立的具有一定功能的函数的集合。库中存放函数的名称和对应的目标代码,以及链接过程中所需的重定位信息。(简单来说就是函数的具体实现方法)

  • Linux中标准的C函数库放置在/usr/lib下,通常以后缀名为.so.a文件存放

  • 用户也可以根据自己的需要建立自己的用户函数库(通过对目标文件进行创建)

  • 函数库分为静态库(.a)和共享库(动态库.so

库函数

  • 存放在函数库中的函数,库函数具有明确的功能、入口调用参数和返回值
  • 库函数的源代码一般是不可见的,但在对应的头文件中可以看到对外的接口(函数原型)

一般来说用户都会将源文件编译成目标文件(二进制文件),然后使用工具将目标文件创建静态库或者动态库,这样做的好处一来是可以方便调用,二来是可以保护源代码的知识产权。

静态库的创建与使用

静态库的概念

  • 静态库就是一些.o目标文件的集合,以.a结尾

  • 静态库在程序链接的时候使用,链接器会将程序中使用到函数代码从库文件中拷贝到可执行文件中。一旦链接完成,在执行程序的时候就不需要静态库了。

    有关编译链接的知识可以查看:一个C程序变为一个可执行程序的过程-CSDN博客

  • 由于每个使用静态库的应用程序都需要拷贝所用函数的代码,所以生成的可执行文件会比较大

静态库的创建

#ar rcs lib库文件名.a 目标文件1 目标文件2 .... 目标文件n

#- ar: 是归档工具,用于处理静态库和目标文件。
#- rcs: 是归档命令的选项,其中 `r` 表示替换现有库中的同名文件,`c` 表示创建新的库(如果不存在),`s` 表示写入索引到库中。
#- lib库文件名.a: 这是要创建的静态库的文件名,通常以 `.a` 结尾。
#- 目标文件1 目标文件2 .... 目标文件n: 这些是要添加到静态库中的源文件或目标文件。

代码示例–静态库的创建和使用

使用之前的代码,源文件是io.c,里边包含文件的拷贝,文件权限等函数,目标文件是io.o文件,最后要被cp.c这个文件调用实现文件的拷贝这个功能。之前的编译流程是将源文件io.c编译成目标文件io.o,然后使用gcccp.c、io.o指定头文件路径和输出文件的路径,指令如下:

gcc src/cp.c obj/io.o -o bin/cp -I include/

现在使用静态库的方法进行编译执行

静态库的创建

image-20240830115043783

这里使用ar工具对目标文件创建静态库的时候最好加一个lib前缀,而且后缀名要以.a结尾,这样做的目的是为了后边和源文件的编译运行。

静态库的使用

#方法一:
gcc -o 可执行文件 调用者的目标文件(将源文件编译成目标文件后使用) -Ldir -l库文件名

#方法二:
gcc -o 可执行文件 -Idir 调用者的源文件 -Ldir -l库文件名

如图所示,使用后缀名为.o的目标文件创建成缀名为.a静态库文件,然后将源文件cp.c一起编译。

image-20240830120535056

这里需要使用-L的参数来指定库文件的路径和使用-l的参数指定要链接到哪一个库,链接库的时候不用写lib前缀和.a后缀,直接掐头去尾写中间的名字即可。

  • -Ldir选项表示将指定的库文件所在目录加入到库搜索路径中,默认的库搜索路径在/usr/lib目录下

  • -lname选项(前缀lib不要加上)表示库搜索路径下的libname.alibname.so文件,这也是为什么库文件都以lib开头的原因之一,如果库文件不是以lib开头(例如hello.a),那么就不能用-l选项,而是直接写上hello.a,将原来-lhello换成hello.a即可。所以在进行静态库创建的时候前边加lib前缀算一种规范,方便后边的编译链接操作。

  • -l是链接器选项,必须放到被编译和链接的文件后面

  • 删除静态库文件后不会影响到可执行文件的运行。由于在编译链接的过程中在源文件中用到的静态库中的函数等已经被加入到可执行文件里,所以最后生成的可执行文件和静态库已经没有联系,删掉静态库也并不会影响可执行文件的运行。

    image-20240830153943963

共享库的创建和是使用

共享库的概念

  • 共享库即动态链接库,在Linux中以.so(share object)为后缀,Windows中以.dll为后缀
  • 共享库在程序链接时候并不像静态库那样会拷贝使用函数的代码,而只是做些标记。在程序开始启动(实际上在加载程序时)运行的时候,加载所需的函数。
  • 可执行程序在运行的时候仍然需要共享库的支持
  • 共享库链接出来的文件比静态库要小得多
  • C语言中所有标准的共享库放置在/usr/lib目录中

结合上边几句话的概括:当一个可执行程序运行起来就变成了一个进程,而系统会给每一个进程分配一个虚拟内存。其中大部分是用户空间,当共享库被做了标记以后,此时共享库中被标记的函数就会被加载到用户空间的代码段。所以它这个是只有运行的时候才会加载到内存里,正因为这样它的可执行程序会比静态库编译出来的可执行文件会小得多,并且它的每次执行都依赖于动态库,如果动态库删除,可执行文件就不能运行了。

共享库的创建

gcc -shared -fPIC -o lib库文件名.so 目标文件1...目标文件n

#-shared表示是使用共享库
#-fpic或者-fPIC表明创建产生独立目标代码,具体应用取决于平台

image-20240830163025297

共享库的使用

#方法一:
gcc -o 可执行文件 调用者的目标文件 -Ldir -l库文件名

#方法二:
gcc -o 可执行文件 -Idir 调用者的C源文件 -Ldir -l库文件名

image-20240830163139431

  • 运行可执行文件出错解决方案(库文件找不到)

    image-20240830162358435

    解决方法

    • 将生成的动态库拷贝到/usr/lib目录下去(需要超级用户权限)

      sudo cp libio.so /usr/lib
      

      image-20240830162849139

    • 设置一个临时的环境变量(需要注意的是因为是一个临时的环境变量所以换一个终端或者重启一下就不生效了)

      export LD_LIBRARY_PATH=库文件的目录
      

      image-20240830163320380

  • 删除共享库文件后运行可执行文件出错(提示找不到库文件)

    image-20240830163910334

总结

前边说的静态库的链接是将编译好的静态库在链接的过程将所用到的函数等功能复制到可执行文件里去,而动态库的链接是将编译好的动态库做一些标记。当运行可执行程序时,在加载过程中将其标记的函数等功能加载到虚拟内存的代码段中。所以相对比下来通过静态库链接后的可执行文件会比动态库链接后的可执行文件大得多。由于它们实现的原理不一样,所以可执行文件在脱离静态库后还能运行,而动态库不行。

image-20240830170007038

image-20240830170416395

如图所示,首先使用ar创建一个静态库,然后使用gcc工具进行链接,最后生成cp1的可执行文件,然后使用gcc工具创建一个动态库,然后使用gcc工具进行链接,最后生成cp2的可执行文件。然后使用ls -l对比两个可执行文件可以发现经过静态库链接后的文件大小远大于链接动态库后的文件。并且可以发现静态库删掉以后可执行文件仍然能运行,而动态库不行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2095524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业内部通信软件:打造高效协同办公的IM即时通讯工具

在现代企业中,高效的内部通信和协同办公是保持竞争优势的重要因素。为了实现团队间的快速沟通和协作,许多企业采用了企业内部通信软件,其中包括IM即时通讯工具。本文将探讨企业内部通信软件的重要性以及如何利用IM即时通讯工具打造高效协同办…

Clickhouse 为什么这么快

Clickhouse 的缘起 Clickhouse 最初是为 Yandex.Metrica 这个世界上第二大的Web分析平台开发的,并且一直是这个系统的核心组件。ClickHouse在Yandex.Metrica中的主要任务是使用非聚合数据在在线模式下构建报告,使用374台服务器组成的集群,在…

服务器间进行文件传输-SFTPSCP一篇搞定

1.简单介绍一下 在一些特殊场景,两台服务器之间需要进行文件传输的时候,或许我们会想到FTP,这也是我们常见的实现方式,但是如果我们不能操作远程服务器,无法判断远程服务器是否安装了FTP呢,众所周知&#…

学习周报-2024.8.31

目录 摘要 Abstract 创新点总结 模型数学原理 实验设置 一、验证实验 二、对比实验 摘要 这周重新梳理出论文的三个创新点,对所提出方法进行数学原理验证,证明其可行性。重新设置了实验部分,分为验证实验和对比实验,一共四…

使用 Eigen 库中的 Kronecker 积运算

前言 在数值计算和线性代数的众多应用中,Kronecker 积(Kronecker Product)是一种常用的矩阵运算。Eigen 是一个高性能的 C 数值计算库,广泛用于科学计算和工程应用中。在 Eigen 库中,Kronecker 积运算属于不常用的扩展…

资料分析(1)

1)截三个数去做&#xff0c;属于马上进位了&#xff0c;差距小&#xff0c;1/19<10% 2)截两位数去做&#xff0c;1/18>10% 3)次位差分别是:3&#xff0c;4&#xff0c;1&#xff0c;选项差距分别是大&#xff0c;大&#xff0c;小 截尾不需要考虑数量级 算一半&#xff0…

抽奖项目技术亮点

活动是通过秒杀领取的。&#xff08;即&#xff1a;活动对应着某一商品&#xff09; 这里超卖指&#xff1a;对于一个活动它的参与量有数量限制&#xff0c;就是活动的库存&#xff0c;当活动的领取数大于活动库存总量&#xff0c;就是超卖 用户秒杀参与活动的资格&#xff08;…

一.海量数据实时分析-Doris入门和安装

前言 停了一个月又开始写文章啦&#xff0c;因为公司数据量达到了几十亿&#xff0c;老板需要做实时数据分析&#xff0c;报表看板。这么大的数据量比较好的选择是使用Doris来做&#xff0c;他可以脱离hadoop生态独立使用所以大受企业喜爱&#xff0c;也因为如此就有了这个系列…

【JavaWeb】Http请求与响应

文章目录 Http 请求与响应一、Http 请求格式1、请求行2、请求头3、请求体&#xff08;post请求才有&#xff09; 二、HttpServletRequest1、获取 请求行 信息2、获取 请求头 信息3、获取 请求参数 信息 三、Http 响应格式1、响应行2、响应头3、响应体&#xff08;正文&#xff…

AI大模型应用开发环境配置

目录 一、工具下载 1、Python官网下载 2、Pycharm官网下载 3、Streamlit官网下载 二、升级PIP &#xff08;一&#xff09;检查PIP版本 &#xff08;二&#xff09;在anaconda Prompt命令窗口输入 三、安装openai组件 四、安装streamlit组件 五、启动streamlit 一、工…

Voi滑板车公司助农扶商,着手打造流量板块

Voi滑板车公司助农扶商&#xff0c;着手打造流量板块。 吉林是粮食大省&#xff0c;是全国优质粳稻主产区&#xff0c;现阶段全省水稻年产量600多万吨&#xff08;商品量400万吨左右&#xff09;&#xff0c;占东北三省一区的24%。巍巍长白山、悠悠松江水&#xff0c;辽阔黑土…

Qt:玩转QPainter序列九(文本,文本框,填充)

前言 继续承接序列八 正文 1. drawImage系列函数 绘制图像 inline void drawImage(const QPoint &p, const QImage &image); 作用: 在指定的点 p 上绘制 QImage 图像。图像的左上角将对齐到 p 点。 inline void drawImage(int x, int y, const QImage &image,…

若依 Vue3的前后端分离系统管理 创建

RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|RuoYi开发文档|若依开发文档|Java开源框架|Java|SpringBoot|SrpingBoot2.0…

【JPCS独立出版】第四届电气工程与计算机技术国际学术会议(ICEECT 2024,9月27-29)

第四届电气工程与计算机技术国际学术会议&#xff08;ICEECT2024&#xff09;将于9月27日-29日在哈尔滨举办。 会议主要围绕"电路与系统"、“电气工程材料”、“计算机视觉”、“计算机技术”等专业研究领域展开讨论。旨在为气工程、计算机技术等领域的专家学者及企业…

Java EE

Java EE 包含JavaSE 增加一些新的API 构建一个后端服务 网页->web服务器->java后端 web后端(javaEE)程序需要运行在服务器中的&#xff0c;这样前端才可以访问得到 服务器&#xff1a;是容器&#xff0c;是连接用户和程序之间的中间件 解释1&#xff1a;一款软件&#…

HBase 部署及shell操作

HBase 数据库 一、HBase 概述1.1 HBase 是什么HBase 的特点 二、HBase 模型及架构2.1 HBase 逻辑模型2.2 HBase 数据模型2.3 HBase 物理模型2.3.1 列簇物理模型2.3.2 Rowkey 字段排序2.3.3 Region 存储到不同节点2.3.4 Region 结构 2.4 HBase 基本架构 三、搭建 HBase 分布式集…

【Linux】线程结束

目录 线程安全和重入 死锁 STL中的容器不是线程安全的 线程安全的单例模式 自旋锁 读者写者问题 线程安全和重入 线程安全&#xff1a;多个线程并发执行同一段代码时&#xff0c;不会出现不同的&#xff08;异常的&#xff09;结果&#xff0c;我们就说线程是安全的。常见…

如何学好文件操作,快来看这篇文章(沉淀中)!!!!

文章目录 1. 为什么使用文件&#xff1f;2. 什么是文件&#xff1f;2.1 程序文件2.2 数据文件2.3 文件名 3. ⼆进制文件和文本文件&#xff1f;4. 文件的打开和关闭4.1 流和标准流4.1.1 流4.1.2 标准流 4.2 文件指针4.3 文件的打开和关闭 5. ⽂件的顺序读写5.1 顺序读写函数介绍…

jQuery库

注明&#xff1a;本文参考自&#xff1a;jQuery - 白月黑羽 (byhy.net) jQuery安装 Download jQuery | jQuery下载到本地 ps: script标签中的src属性&#xff1a;表示包含要执行的代码的外部文件位置 <!DOCTYPE html> <html lang"en"><head><s…

unity游戏开放:标记物体 一目了然

Unity游戏开发:标记物体,让开发变得一目了然 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发:标记物体,让开发变得一目了然前言1. 什么是Tag&#xff1f;2. Unity中如何添加和管理Tag步骤1&am…