Linux(11)动静态库生成与安装

news/2024/4/25 14:10:08/文章来源:https://blog.csdn.net/CegghnnoR/article/details/127619795

文章目录

  • 生成动静态库
  • 使用动静态库

对之前内容的复习:👉 [Linux](5)gcc编译、gdb调试、make/makefile项目自动化构建工具、进度条小程序_世真的博客-CSDN博客

  • 静态库(.a)︰程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so)︰程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamiclinking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

生成动静态库

有这样四个文件:

mymath.h 头文件什么一个累加函数

// mymath.h
#pragma once#include <stdio.h>
#include <assert.h>// 累加
extern int addToVal(int from, int to);

累加函数的实现

// mymath.c
#include "mymath.h"int addToVal(int from, int to)
{assert(from <= to);int result = 0;for (int i = from; i <= to; ++i){result += i;}return result;
}

myprint.h 头文件声明一个打印函数

// myprint.h
#pragma once #include <stdio.h>
#include <time.h>extern void Print(const char* msg);

打印函数的实现,打印字符串和当前时间

#include "myprint.h"void Print(const char* msg)
{printf("%s : %lld\n", msg, (long long)time(NULL));
}

makefile:

mymath.o:mymath.cgcc -c mymath.c -o mymath.o
myprint.o:myprint.cgcc -c myprint.c -o myprint.o
.PHONY:clean
clean:rm -f *.o

将它们都处理成可重定位二进制文件(.o)

使用 ar -rc 命令将 .o 文件打包成静态库

ar -rc libmymath.a mymath.o myprint.o

生成动静态库的makfefile:

.PHONY:all
all:libmymath.so libmymath.alibmymath.so:mymath.o myprint.ogcc -shared -o libmymath.so mymath.o myprint.o
mymath.o:mymath.cgcc -fPIC -c mymath.c -o mymath.o
myprint.o:myprint.cgcc -fPIC -c myprint.c -o myprint.olibmymath.a:mymath_s.o myprint_s.oar -rc libmymath.a mymath_s.o myprint_s.o
mymath_s.o:mymath.cgcc -c mymath.c -o mymath_s.o -std=c99
myprint_s.o:myprint.cgcc -c myprint.c -o myprint_s.o -std=c99.PHONY:lib
lib:mkdir -p lib-static/libmkdir -p lib-static/includecp *.a lib-static/libcp *.h lib-static/includemkdir -p lib-dyl/lib mkdir -p lib-dyl/includecp *.so lib-dyl/lib cp *.h lib-dyl/include.PHONY:clean
clean:rm -rf *.o *.a *.so lib-static lib-dyl

使用动静态库

静态库

  1. 通过相对路径包含头文件
#include "./lib-static/include/mymath.h"
#include "./lib-static/include/myprint.h"int main()
{int start = 0;int end = 100;int result = addToVal(start, end);printf("result: %d\n", result);Print("hello world");return 0;
}
  1. 将头文件和我们编写的程序放在同一路径下,包含头文件就可以不用带路径了
  2. 将头文件放在系统头文件路径下/user/include,包含头文件也可以不用带路径了

光是这样写还不行,它会报链接错误

[CegghnnoR@VM-4-13-centos test]$ gcc mytest.c -o mytest
/tmp/cc8M56hj.o: In function `main':
mytest.c:(.text+0x21): undefined reference to `addToVal'
mytest.c:(.text+0x42): undefined reference to `Print'
collect2: error: ld returned 1 exit status

这是因为找不到库文件,所以库文件也应该拷贝到系统路径下。

将自己的头文件和库文件,拷贝到系统路径下的过程就叫做库的安装。

不过这种方式不推荐,容易污染系统头文件和库。


我们还有一种方式去只用自己的库

gcc mytest.c -o mytest -I ./lib-static/include/ -L ./lib-static/lib/ -l mymath

使用 gcc -I 选项指定头文件所在目录,使用 -L 选项指定库文件所在目录,使用 -l 选项指定要包含的库名(去掉前缀lib和后缀.a)

动态库

和静态库一样去指定头文件目录、库文件目录、库名

gcc mytest.c -o mytest -I ./lib-dyl/include/ -L ./lib-dyl/lib/ -l mymath

编译成功,但是运行会出问题:

[CegghnnoR@VM-4-13-centos test]$ ./mytest
./mytest: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

使用 ldd 查看程序依赖的库:

[CegghnnoR@VM-4-13-centos test]$ ldd mytestlinux-vdso.so.1 =>  (0x00007ffdc9def000)/$LIB/libonion.so => /lib64/libonion.so (0x00007f2c913c4000)libmymath.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00007f2c90edd000)libdl.so.2 => /lib64/libdl.so.2 (0x00007f2c90cd9000)/lib64/ld-linux-x86-64.so.2 (0x00007f2c912ab000)

运行时链接不到库,因为我们只告诉了 gcc 各种路径。而动态库是程序运行时去链接的,我们的进程找不到对应的动态库。

解决方法

  1. 将动态库拷贝到系统路径下/lib64

  2. 导入环境变量 —— 程序运行时会在环境变量中查找自己需要的动态库路径

    LD_LIBRARY_PATH
    

    将自己的库文件的绝对路径添加到这个环境变量中,注意用 : 分隔

  3. 系统配置文件

  4. 软链接


程序运行需要把代码和数据加载到内存,那么动态库被加载到内存的哪个区了呢?

动态库被加载到物理内存后,会被映射到虚拟进程地址空间的共享区。如果有其他进程也要使用这个动态库,系统不会重新加载这个动态库,而是直接将它映射到该进程的共享区。所以一个动态库在内存中只会加载一份,是可以被多个进程共享的,所以动态库又叫共享库。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL学习十九、使用游标

游标&#xff08;cursor&#xff09;是一个存储在 DBMS 服务器上的数据库查询&#xff0c; 它不是一条 SELECT 语句&#xff0c;而是被该语句检索出来的结果集。在存储了 游标之后&#xff0c;应用程序可以根据需要滚动或浏览其中的数据。 我们通常的检索操作会返回一组称为结…

vue3+antd中使用Dayjs实现输出的日期格式化,和限制自定义日期选择器的可选范围

场景复现 在vue3antd项目中用到了日期选择器&#xff0c;但是默认的日期选择的结果是标准的日期格式&#xff0c;我们往往需要对最后的结果进行一定的格式化输出 一般输出的是这种标准的数据格式 如果我们想对时间进行指定的格式化输出&#xff0c;通常大家会想到moment&…

如何在页面中制作悬浮发布按钮弹窗

效果展示&#xff1a; 前置准备&#xff1a; 1.已搭建好&#xff0c;待添加悬浮层的页面 2.icon素材 具体步骤&#xff1a;&#xff08;3&#xff09; 1.添加悬浮层页面 2.配置悬浮层关闭触发器 3.配置首页发布icon触发器和动画 步骤分解&#xff1a; 1.添加悬浮层页面 1.1…

2022 年跨境电商要尝试的 25 个黑五营销技巧

关键词&#xff1a;黑五营销、黑色星期五活动、跨境电商黑五 我们汇总了以下最佳跨境电商黑五创意清单&#xff1a; 黑五营销技巧分享 如何宣传您的黑色星期五优惠 小型企业的黑五营销创意 黑五营销提示 随意跳到您最感兴趣的部分&#xff0c;或通读它们&#xff0c;看看…

JAVA序列化和反序列化学习笔记

0x01 开始学习JAVA反序列化&#xff0c;参考 《安全漫谈》和feng师傅的文章一步一步来&#xff0c;希望 能赶在这个学期学完java最基础的东西&#xff0c; 笔记做到这里方便自己查阅&#xff0c;也是事先实操了一下 &#xff0c;才写的笔记 概念&#xff1a; JAVA 序列化 就是…

program arguments,vm arguments,environment variable

作者:david_zhang@sh 【转载时请以超链接形式标明文章】 https://www.cnblogs.com/david-zhang-index/p/16846493.html 参数太多,傻傻分不清楚,简单说 1,program arguments是main函数args[]参数 2,vm arguments是java环境变量 3,environment variable是jvm环境变量 看代码…

华为设备配置NAT原理与示例

网络地址转换NAT 文章目录网络地址转换NAT1 NAT概述1.1 NAT产生的技术背景1.2 私有IP地址1.3 NAT技术原理2 静态NAT2.1 静态NAT原理2.2 静态NAT转换示例2.3 静态NAT配置介绍2.4 静态NAT配置示例3 动态NAT3.1 动态NAT原理3.2 动态NAT转换示例3.3 动态NAT配置介绍3.4 动态NAT配置…

resultMap结果映射

文章目录一、resulrMap结果映射二、驼峰命名自动映射查询结果的列名和Java对象的属性名对应不上怎么办&#xff1f; *第一种方式&#xff1a;as给列名起别名 *第二种方式&#xff1a;使用resultMap进行结果映射 *第三种方式&#xff1a;是否开启驼峰命名自动映射&#xff08;配…

算法学习:动态规划

14天阅读挑战赛 努力是为了不平庸~ 系列文章目录 第一章 算法简介 第二章 贪心算法 第三章 分治法 第四章 动态规划 目录系列文章目录2.0兔子序列2.1动态规划基础2.2最长的公共子序列2.2.1问题描述&#xff1a;2.2.2分析问题&设计思路&#xff1a;2.2.3图解思路&#xff1…

Python抓取我的CSDN粉丝数,白嫖GithubAction自动抓取

《Python抓取我的CSDN粉丝数&#xff0c;白嫖GithubAction自动抓取》 一.介绍 这段时间我想申请CSDN的博客专家认证&#xff0c;但是我发现我的总访问量不够&#xff08;博客专家的总访问量要大于20万&#xff09;&#xff0c;所以我就想把我的CSDN每天的 【总访问量】&#…

芯片与自动驾驶技术漫谈

芯片与自动驾驶技术漫谈 从芯片到系统国产,信创产业如何4步走上自主路? 信创产业发展是国家经济数字化转型、提升产业链发展的关键。我国明确了“数字中国”建设战略,抢占数字经济产业链制高点。推进信创产业的发展,促进信创产业在区域性落地生根,带动传统IT信息产业转型,…

【光通信】常见光模块与光纤收发器说明及作用区别

&#xff1a;单纤收发器是指采用的是单模光缆 单纤收发器是只用一根芯&#xff0c;两端都接这根芯&#xff0c;两端的收发器采用不同的光波长&#xff0c;所以能在一根芯里传输光信号。 双纤收发器就是采用了两根芯&#xff0c;一根发送一根接收&#xff0c;一端是发的另一端就…

MongoDB 分片集群均衡器导致的性能下降

近期&#xff0c;有人反馈其mongodb分片集群&#xff0c;在加载处理大批量数据时&#xff0c;程序处理十分缓慢并且应用还会报错&#xff1a;version mismatch detected for 。现将分析汇总如下备用。 一、问题现象 负责同事反馈9月1日18:52分左右&#xff0c;应用报错version…

计算机毕业设计(附源码)python医院预约挂号管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

学习笔记-php伪协议

伪协议 相关文章 & Source & Reference PHP伪协议的妙用 filter协议 php://filter 是一种元封装器&#xff0c; 设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用&#xff0c;类似 readfile()、 file() 和 file_get_contents()&#x…

网课查题系统搭建-查题校园题库

网课查题系统搭建-查题校园题库 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&…

【C++笔记】第十九篇 多态

C的多态 1. 多态简介 ① 多态是C面向对象三大特性之一。 ② 多态分为两类&#xff1a; 静态多态&#xff1a;函数重载和运算符重载属于静态多态&#xff0c;复用函数名。动态多态&#xff1a;派生类和虚函数实现运行时多态。 ③ 静态多态和动态多态区别&#xff1a; 静态…

【源码分析】Spring中的设计模式——Context与Factory的关系

省流助手 两个类都实现了同一个接口&#xff0c;但是其中一个类对接口的实现是通过调用另一个类的接口实现来实现的&#xff0c;这就是静态代理模式(也可以说是装饰器模式&#xff0c;这俩区别不大) 这个例子中就是AbstractBeanFactory和AnnotationConfigApplicationContext都…

电子签批板那个品牌好用?国产柜台电子签名板推荐

如今已正式迈入数字时代&#xff0c;电子合同、电子签名不再新奇&#xff0c;各行各业对电子签名呈现出多元化的细分需求&#xff0c;应用场景也更加广泛。目前通信、银行、保险、酒店、政务等有柜台业务服务的领域大多都已配备了电子签字板用以替代传统纸张业务办理流程。加上…

First time to know JAVA

文章目录前言1.JAVA语言概述1.1 JAVA是什么&#xff1f;1.2 JAVA语言的重要性1.3 JAVA语言的发展简史1.4 JAVA语言的特性2.初识JAVA的main方法2.1 main方法示例2.2 运行JAVA程序3.JAVA中的注释3.1 JAVA注释的基本规则3.2 JAVA注释规范4.初始JAVA中的标识符5.初始JAVA中的关键字…