Linux共享库基础及实例
共享库是将库函数打包成一个可执行文件,使得其在运行时可以被多个进程共享。
目标库
回顾下构建程序的一种方式:
将每个源文件编译成目标文件,再通过链接器将这些目标文件链接组成一个可执行程序。
gcc -g -c prog.c mod1.c mod2.c
gcc -g -o prog prog.o mod1.o mod2.o
库分为静态的和共享的。
静态库
静态库是一个保存所有被添加到其中的目标文件的副本的文件。其名称形式libname.a。
可以通过ar命令来创建和维护静态库
ar options archive object-files ...
#比如创建静态库
ar r libtest.a test1.o test2.o test3.o
#比如从静态库中删除一个模块
ar d libtest.a test2.o
使用静态库有两种方法
-
gcc -g -o prog prog.o libtest.a
-
gcc -g -o prog prog.o -Lxxx -ltest
, 通过-L执行搜索目录和-l指定库名称
创建共享库
静态库有一些缺陷:
-
多个静态库如果都使用到同一个目标文件,那么存储同一个目标文件的多个副本将会浪费磁盘空间
-
如果多个程序都使用到了这个同一个目标文件,那么每个程序会在虚拟内存中独立保存一份该目标文件的副本,提高了整体虚拟内存使用量
-
如果这同一个目标文件修改了, 那么使用到这个目标文件的多个静态库都要重新链接
所以,需要设计出共享库机制。
共享库的目标思想是目标文件的单个副本由所有需要使用它的程序共享。
由第一个需要使用该目标文件的程序启动时,将该目标文件的副本运行加载进内存,后面的程序如果也需要使用该目标文件,直接使用已经被加载进内存的副本即可。
虽然共享库的代码是共享的,但其中的变量不是共享的,每个使用库的程序会拥有自己在库中定义的全局和静态变量的副本。
创建一个共享库
gcc -g -c -fPIC -Wall mod1.c mod2.c mod3.c
gcc -g -shared -o libfoo.so mod1.o mod2.o mod3.o
共享库的前缀是lib,后缀是.so。
-fPIC选项:编译器应该生成位置独立的代码,这样共享库代码可以放到任意一个虚拟地址处。
也可以使用一行命令来生成共享库
gcc -g -fPIC -Wall mod1.c mod2.c mod3.c -shared -o libfoo.so
使用共享库也有两种方法
-
gcc -g -o prog prog.o libfoo.so
-
gcc -g -o prog prog.o -Lxxx -lfoo
, 通过-L执行搜索目录和-l指定库名称
程序启动时可以通过LD_LIBRARY_PATH来指定库的位置。
共享库别名soname
如果一个共享库有别名soname,则静态链接时会将soname嵌入到可执行文件中,而不使用真实名字。
gcc -g -c -fPIC -Wall mod1.c mod2.c mod3.c
gcc -g -shared -Wl,-soname,libbar.so -o libfoo.so mod1.o mod2.o mod3.o
通过**-Wl,-soname**参数设置共享库libfoo.so的别名为libbar.so,这样程序在链接共享库libfoo.so的时候嵌入的就是libbar.so名字,所以还需要一步,创建软连接:
ln -s libfoo.so libbar.so
soname的目的是为了提供一层间接层,使得可执行程序能够在运行时使用与链接时使用的库不同的(但兼容的)共享库。
版本和命名
真实名字命名规则
libname.so.major-id.minor-id
,比如libdemo.so.1.0.1,第一个数字是主版本号,第二个数字是次版本号,第三个数字是该次版本中的修订号或补订号。
soname命名规则
libname.so.major-id
,比如libdemo.so.1,只需要包含主版本号。
libname.so.1 --> libdemo.so.1.0.1
通常还会创建一个链接器名称,比如libdemo.so,没有版本号。链接器铭名称可以链接到soname也可以链接到真实名字,一般链接到soname。
libname.so --> libname.so.1
libname.so.1 --> libname.so.1.0.1
动态加载库
在linux中可以通过dlopen API组来打开使用共享库。
构建程序时必须使用-ldl选项链接libdl库
主要的函数有dlopen(), dlsym(), dlclose(), dlerror()等:
#include <dlfcn.h>
void *dlopen(const char *filename, int flags); //打开共享库
void *dlsym(void *handle, const char *symbol); //查找符号
int dlclose(void *handle); //关闭共享库
char *dlerror(void); //错误诊断
控制符号可见性
如果共享库中的某个函数不想被导出symbol给外部访问,可以怎么做?
-
C程序中可以使用static关键词使得函数符号私有
-
gcc编译器提供了一个声明特性,与static效果类似
void __attribute__((visibility("hidden"))) fun(void) { }
LD_PRELOAD
LD_PRELOAD环境变量的设置可以使得程序预加载指定的库,或者通过文件**/etc/ld.so.preload**来控制预加载库也是一样的。
LD_DEBUG
LD_DEBUG环境变量可以帮助监控动态链接器到底在搜索那些库,比如
LD_DEBUG=libs xxx
可以监控程序xxx执行时搜索的库的路径。
代码实例
源码参考share_lib文件夹
testfun.c
#include <stdio.h>
void testfun(void) {printf("this is testfun\n");
}
dyload.c
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>int main(int argc, char *argv[])
{void *libHandle;void (*funcp)(void);const char *err;if (argc != 3 || strcmp(argv[1], "--help") == 0) {printf("usage: %s <lib-path> <func-name>\n", argv[0]);return 0;}libHandle = dlopen(argv[1], RTLD_LAZY);if (libHandle == NULL) {printf("dlopen: %s", dlerror());return -1;}(void) dlerror();*(void **)&funcp = dlsym(libHandle, argv[2]);err = dlerror();if (err) {printf("dlsym: %s\n", err); return -1;}if (!funcp) {printf("%s is NULL\n", argv[2]);return -1;}else {printf("%s addr is: %p\n", argv[2], funcp);}(*funcp)();dlclose(libHandle);return 0;
}
Makefile
src1:=dyload.c
obj1:=dyload
src2:=testfun.c
obj2:=libtestfun.soall:${src1} ${src2}gcc -g -fPIC -Wall ${src2} -shared -o ${obj2}gcc -g -o ${obj1} ${src1}./${obj1} ./${obj2} testfunclean:@rm ${obj1} ${obj2}
执行效果,dyload执行时打印出libtestfun.so中testfun函数的地址,并执行该函数。
root@pc:share_lib# make
gcc -g -fPIC -Wall testfun.c -shared -o libtestfun.so
gcc -g -o dyload dyload.c
./dyload ./libtestfun.so testfun
testfun addr is: 0x7f694b0f8119
this is testfun
参考文献
《linux programming interface》part42-43
相关文章:

Linux共享库基础及实例
共享库是将库函数打包成一个可执行文件,使得其在运行时可以被多个进程共享。 目标库 回顾下构建程序的一种方式: 将每个源文件编译成目标文件,再通过链接器将这些目标文件链接组成一个可执行程序。 gcc -g -c prog.c mod1.c mod2.c gcc -g …...

java八股文面试[java基础]——final 关键字作用
为什么局部内部类和匿名内部类只能访问final变量: 知识来源 【基础】final_哔哩哔哩_bilibili...

Redis 分布式锁存在什么问题 ?如何解决 ?
目录 1. 如何实现分布式锁 2. Redis 分布式锁存在什么问题 2.1 解决死锁问题 2.2 解决锁误删问题 1. 如何实现分布式锁 Redis 天生就可以作为一个分布式系统来使用,所以它实现的锁都是分布式锁。 Redis 可以通过 setnx(set if not exists)…...

n5173b是德科技keysight N5173B信号发生器
产品概述 是德科技/安捷伦N5173B EXG模拟信号发生器 当您需要平衡预算和性能时,是德科技N5173B EXG微波模拟信号发生器是经济高效的选择。它提供解决宽带滤波器、放大器、接收机等参数测试的基本信号。执行基本LO上变频或CW阻塞,低成本覆盖13、20、31.…...
React源码解析18(10)------ 实现多节点的Diff算法
摘要 在上一篇中,实现了多节点的渲染。但是之前写得diff算法,只能适用于单节点的情况,例如这种情况: <div><p><span></span></p> </div>如果对于多节点的情况: <ul><…...
Linux指令篇!
Linux 是一个广泛使用的开源操作系统,以下是一些常用的 Linux 知识点和指令: 1. 文件和目录操作: - ls:列出目录内容 - cd:切换目录 - pwd:显示当前工作目录 - mkdir:创建目录 - touch…...
Vue2学习笔记のVue组件化编程
目录 Vue组件化编程非单文件组件基本使用几个注意点组件的嵌套VueComponent一个重要的内置关系 单文件组件index.htmlmain.jsApp.vueSchool.vueStudent.vue 各位小伙伴们好呀,不知道上一篇文章你是否有收获!这篇是Vue2学习笔记第二篇,也是Vue…...

跨境电商儿童沙画办理EN71测试标准
儿童沙画就是小孩子玩的那种用彩色沙子或者彩色墨水,在有图形轮廓的纸片上去绘画,可以按照儿童沙画底板上的人物轮廓线条,动物线条,风景线条,动漫线条,去添加自己喜欢的颜色,让单调的线条变成自…...

chrome浏览器账号密码输入框自动填充时背景色不变
处理前 使用延时的方式解决 .login-box input,password:-webkit-autofill .login-box input,password:-webkit-autofill:hover, .login-box input,password:-webkit-autofill:focus, .login-box input,password:-webkit-autofill:active {-webkit-transition-delay: 999999…...

【ARM】Day9 cortex-A7核I2C实验(采集温湿度)
1. 2、编写IIC协议,采集温湿度值 iic.h #ifndef __IIC_H__ #define __IIC_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "led.h" /* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4* I2C1_S…...

【Leetcode】移动零
移动零 题目描述算法描述编程代码 链接: 移动零 题目描述 算法描述 编程代码 class Solution { public:void moveZeroes(vector<int>& nums) {//题目要求不可以复制数组,开辟额外空间int dest -1,curr 0;for(;curr < nums.size();curr){if(nums[cu…...

数据结构入门 — 顺序表详解
前言 数据结构入门 — 顺序表详解 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 文章目录 前言一、顺序表1. 顺序表是什么2. 优缺点 二、概念及结构…...

SimpleCG绘图函数(9)--绘制各种线条
一、所有线段函数概述 可填充图形绘制函数都介绍完了,还有一些特殊线条的绘制将在本篇进行讲解。所有特殊线条函数如下所示,其中还有一个区域填充函数floodfill比较特殊,是配合线条函数使用的: //绘制一系列折线段 //折线段以一组…...

RISCV 6 RISC-V加载存储指令
RISCV 6 RISC-V加载存储指令 1 RV32I Load and Store Instructions1.1 LOAD instructions1.1.1 加载指令的指令格式1.1.2 加载指令在使用时需要注意的点 1.2 STORE instructions1.2.1 存储指令的指令格式1.2.2 存储指令在使用时需要注意的点 2 RV64 Load and Store Instruction…...
木叶飞舞之【机器人ROS2】篇章_第二节、turtlebot3安装
没有真实小车的情况下,利用gazebo的仿真,操作小乌龟来学习ros2。废话不多说,直接上命令。 Install Gazebo sudo apt install ros-humble-gazebo-*Install Cartographer 假如前一节未安装源码版本的cartographer,那就安装apt版本…...

【论文阅读】自动驾驶安全的研究现状与挑战
文章目录 摘要1.引言1.1.自动驾驶安全1.2.攻击面1.3.内容和路线图 2.自动驾驶技术2.1.组成2.2.技术 3.传感器安全3.1.照相机3.2.GNSS(全球导航系统)/IMU(惯性测量单元)3.3.超声波传感器3.4.毫米波雷达3.5.激光雷达3.6.多传感器交叉…...

标签打印小工具 选择图片打印,按实际尺寸打印。可旋转图片
您可以尝试使用以下标签打印工具: 柯尼卡美能达标签打印机:功能齐全、易于使用的打印机,支持各种标签尺寸和类型。 赛门铁克标签打印机:高速打印、可靠性强的打印机,支持多种操作系统和软件。 齐柏林标签打印机&…...

什么是深拷贝和浅拷贝?
面试回答 在计算机内存中,每个对象都有一个地址,这个地址指向对象在内存中存储的位置。当我们使用变量引用一个对象时,实际上是将该对象的地址赋值给变量。因此,如果我们将一个对象复制到另一个变量中国,实际上是将对象…...

安装docker服务及docker基本操作
一、docker安装(yum安装) 基于centos7 1.添加docker-ce 源信息 安装依赖包(yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要device-mapper-persistent-data 和 lvm2) yum install yum-…...
【项目经验】:项目中下拉框数据太多造成页面卡顿(二)
一.项目需求 下拉框下拉列表数据是由后端返回的,而且他会变化,所以数据不是写死的而且数据量大。上一篇博客http://t.csdn.cn/sSNTa我们是用的数据懒加载的方式,这次我们使用远程搜索的方式解决这个问题。 二.用到的组件方法介绍 filterabl…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...

前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...