当前位置: 首页 > ops >正文

Linux基础IO(十)之静态库(后续出动态库)

文章目录

  • 静态库
    • 库搜索路径
    • 生成静态库
    • 使用静态库
    • 结论

静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。

程序运行的时候将不再需要静态库。

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,

而不是外部函数所在目标文件的整个机器码

在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,

这个过程称为动态链接(dynamic linking)

Linux默认是动态库。

动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。

操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,

节省了内存和磁盘空间。

库搜索路径

从左到右搜索-L指定的目录。

由环境变量指定的目录 (LIBRARY_PATH)

由系统指定的目录

/usr/lib
/usr/local/lib

生成静态库

1、拷贝.so文件到系统共享库路径下, 一般指/usr/lib

2、更改 LD_LIBRARY_PATH

[root@localhost linux]# lsadd.c add.h main.c sub.c sub.h[root@localhost linux]# gcc -c add.c -o add.o[root@localhost linux]# gcc -c sub.c -o sub.o

生成静态库

[root@localhost linux]# ar -rc libmymath.a add.o sub.o 

argnu归档工具,rc表示(replace and create)

查看静态库中的目录列表

[root@localhost linux]# ar -tv libmymath.a rw-r--r-- 0/0 1240 Sep 15 16:53 2017 add.orw-r--r-- 0/0 1240 Sep 15 16:53 2017 sub.ot:列出静态库中的文件v:verbose 详细信息[root@localhost linux]# gcc main.c -L. -lmymath-L 指定库路径-l 指定库名

测试目标文件生成后,静态库删掉,程序照样可以运行。

3、ldconfig 配置/etc/ld.so.conf.d/ldconfig更新

mymath.h

#pragma once#include <stdio.h>extern int myerrno;int add(int x,int y);
int sub(int x,int y);
int mul(int x,int y);
int div(int x,int y);

mymath.c

#include "mymath.h"int myerrno=0;int add(int x,int y)
{return x+y;
}
int sub(int x,int y)
{return x-y;
}
int mul(int x,int y)
{return x*y;
}
int div(int x,int y)
{if(y==0){myerrno=1;return -1;}return x/y;
}

我们提供的方法给别人使用:

1.直接把源文件给他

2.把我们的源代码想办法打包成库。提供(库+.h)也就是库+头文件。

必须要给头文件,头文件就相当于方法(库文件)的一份说明书。

静态库原理:

image-20250403214110442

makeflie

lib=libmymath.a$(lib):mymath.oar -rc $@ $^
mymath.o:mymath.cgcc -c $^
.PHONY:clean
clean:rm -rf *.o *.a lib.PHONY:output
output:mkdir -p lib/includemkdir -p lib/mymathlibcp *.h lib/includecp *.a lib/mymathlib 

只有 $^ 就是把源文件形成一个 .o文件

image-20250403225144138

使用静态库

image-20250403225206248

在test里创建main.c

#include "mymath.h"int main()
{printf("1+1=%d\n",add(1,1));return 0;
}

image-20250403220044511

编译时先要进行预处理,展开头文件,而展开头文件就需要先把头文件找到。

gcc编译的时候找math.h会在默认路径(/usr/include/) 或者 当前目录(同级目录) 下找。

image-20250403220357914

解决找头文件路径问题: -I 到指定目录下找头文件 或者 直接在头文件上加上绝对/相对路径

image-20250403220733463

#include "lib/include/mymath.h"

找不到add方法,属于链接报错。(一般.o之类的都属于链接报错)

image-20250403225651474

因为.o文件可以成功生成,所以前三个阶段没问题。

image-20250403221233395

报错原因:找不到对应方法的实现,实现方法在库里面,

找不到静态库,因为只会在默认路径下/当前目录下找对应的静态库。

image-20250403221648197

解决链接报错:-L + 静态库的路径(一定要指定链接哪个库-l

没有指定链接哪个库,就会报错

因为指定路径的目录下可能不仅仅只有一个静态库,

所以要显性告诉gcc要链接哪个库。

image-20250403225553873

在使用 -I 的时候不需要指明头文件,因为源代码里已经指明。

但是需要指明需要链接哪个静态库。

-l后面要跟库的名字!!!(库的名字是去掉lib,去掉.a 剩下的字符串!!!)

而不是整个字符串!!!

image-20250403225813165

image-20250403230411290

c/c++不用带 -I -L -l 是因为

1.头文件默认有

2.路径默认 gcc 能找到

3.因为纯c/c++代码,gcc/g++ 就能认识c/c++的静态库/动态库


把加->除,并且被除数是0

  #include "mymath.h"int main(){//printf("10/0=%d,myerror=%d\n",div(10,0),myerrno);//形参实例化是右→左,所以在执行div之前,myerrno就被赋值为0了int n=div(10,0);printf("10/0=%d,myerror=%d\n",n,myerrno);return 0;                                       } 

image-20250405142118359


如果不想用这么长、这么麻烦的指令:

1.把头文件拷贝到系统的 include 里/库文件拷贝到 lib64 目录下

这样只要指明-l就可以编译通过。

两个 sudo -> 库的安装。

(所谓的安装本质:头文件、库文件拷贝到系统的路径下)

卸载就是把头文件和库文件在特定目录下删除。

image-20250405150828405

2.可以对目录里的头文件建立软链接,把软链接放到include

/把目录里的库也建立软链接,放到 lib64 的目录下,

把软链接放到系统默认的路径下也可以不用带这么多选项了。

image-20250405154743509

#include "myinc/mymath.h"  

image-20250405171411285

结论

1.第三方库,往后在使用的时候,必定要使用 gcc -l

2.深刻理解 errno 的本质

(想让用户知道程序出错了,更想让用户知道程序错哪了)

3.-static 是建议型选项,如果动静态库都有,使用动态链接就默认,使用静态链接就加 -static

gcc 默认是动态链接,但是只提供静态库,所以gcc只能进行静态链接。

(可执行程序可以有两种链接)

image-20250405143342680

4.如果系统中需要连接多个库,则gcc可以连接多个库,-l……

image-20250405171302882

http://www.xdnf.cn/news/2043.html

相关文章:

  • 论分布式事务及其解决方案 架构师论文范文(考试笔记)
  • 计算机操作系统
  • 人口老龄化丨AI健康小屋如何实现防病于未然​
  • HTTP状态码
  • 使用Tortoise-ORM和FastAPI构建评论系统
  • Gmail安卓版邮件同步速度与隐私保护测评【体验对比】
  • 保安员证考试的理论知识有哪些重点?
  • 从原生检索到异构图:Native RAG、GraphRAG 与 NodeRAG 架构全景解析
  • 关注心理健康,开启心灵养生之旅
  • 如何用AI主动突出画面主体!涂鸦新方案助剪辑、工业巡检、医疗影像等领域,实现自动追踪+智能放大
  • BUUCTF-[ACTF新生赛2020]SoulLike
  • 伊克罗德信息亮相亚马逊云科技合作伙伴峰会,以ECRobot 智能云迁移助手在GenAI Tech Game比赛勇夺金牌!
  • 从零开始学Python游戏编程39-碰撞处理1
  • MySQL 从入门到精通
  • 【算法】单词搜索、最短距离
  • 增加首屏图片
  • MCP Server 实现笔记:开发者视角下的优缺点
  • MySQL InnoDB 存储引擎间隙锁(Gap Lock)
  • 《Pinia实战》10.手册
  • 数据结构(java)二叉树的基本操作
  • AI与思维模型【77】——PDCA思维模型
  • 1.2-1.3考研408计算机组成原理第一章 计算机系统概述
  • 【3】GD32 基础外设:GPIO、外部中断、DMA、定时器、实时时钟、看门狗
  • vue next()、next(“/“)、next({...to})、next({...to,replace:true})的区别
  • 机器人行业研究系列报告
  • 遥测终端机,推动灌区流量监测向数据驱动跃迁
  • 《遥测终端机:农业水价改革的智能助手》
  • python 环状图 (pycirclize)
  • AI与思维模型【78】——周哈里窗思维模型
  • 【Java学习笔记】二维数组