动静态库(Linux)
文章目录
- 前言
- 一、静态库
- 二、动态库
- 三、深入理解动态库
- 总结
前言
我们之前用过c语言的库.Linux中默认的都是使用动态库,如果想要使用静态库,就必须加上-static选项。默认都是安装的动态库,系统中一般没有静态库,如果要使用,就需要自己安装。
Linux下动态库是以.so结尾的,静态库是以.a结尾的。
无论是动态库还是静态库,都有自己的名字。比如libc.so,库的名字需要去掉前缀lib,去掉后缀.so,那么这就是一个c标准库。
一、静态库
什么是库呢??
库本质就是把一些.o结合放在一起就是我们使用的库
我们只要拥有.o文件和.h文件就可以调用相关的函数。 比如下面的例子
add.h
#pragma once
int add(int x,int y);
add.c
#include "add.h"
int add(int x,int y)
{return x+y;
}
myfile.c
#include "myfile.h"//打开
myFILE*myopen(const char*path,const char*mode)
{int flag=0;if(strcmp(mode,"w")==0){flag|=O_CREAT|O_WRONLY|O_TRUNC;}else if(strcmp(mode,"a")==0){flag|=O_CREAT|O_APPEND|O_TRUNC;}else if(strcmp(mode,"r")==0){flag|=O_RDONLY;}else{return NULL;}int fd=0;if(flag&O_RDONLY){fd=open(path,flag);}else{umask(0);fd=open(path,flag,0664);}myFILE*fp=(myFILE*)malloc(sizeof(myFILE));fp->inode=fd;fp->pos=0;fp->cap=MAX;fp->flushmode=FLUSHLINE;return fp;}
void myfflush(myFILE*fp)
{write(fp->inode,fp->buffer,fp->pos);fp->pos=0;
}
//写文件
int myfwrite(const void *ptr,size_t n,myFILE*fp)
{//首先放到缓冲区memcpy(fp->buffer+fp->pos,ptr,n);fp->pos+=n;//判断是否需要刷新if(fp->flushmode==1&&fp->buffer[fp->pos-1]=='\n'){myfflush(fp);}if(fp->flushmode==2&&fp->pos==fp->cap){myfflush(fp);}return n;
}
//关闭
void myclose(myFILE*fp)
{//进程退出先刷新myfflush(fp);close(fp->inode);free(fp);
}
myfile.h
#pragma once #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>#define FLUSHLINE 1
#define FLUSHFULL 2
#define FLUSHNO 3
#define MAX 4096typedef struct myFILE
{int inode;char buffer[MAX];int pos;int cap;int flushmode;}myFILE;//打开
myFILE*myopen(const char*path,const char*mode);
//写文件
int myfwrite(const void *ptr,size_t n,myFILE*fp);
//刷新
void myfflush(myFILE*fp);
//关闭
void myclose(myFILE*fp);
测试代码test.c
#include <stdio.h>
#include "add.h"
#include "myfile.h"int main()
{int x=10;int y=20;int sum=add(x,y);printf("%d+%d=%d\n",x,y,sum);myFILE*fp=myopen("file.txt","w");if(fp==NULL) {perror("myopen:");return 1;}int cnt=5;char buffer[64]={"hello world\n"};while(cnt--){myfwrite(buffer,64,fp);}myclose(fp);return 0;
}
1.正常测试
下面是我们的结构,我们自己写了两个add和myfile两个函数文件1,我们并不像把.c文件给user,但是好像让他用我们的函数,我们就可以把.o和.h给他,然后这个用户自己写main函数就可以。
我们测试一下效果
我们运行看一下结果
确实完成了我们的任务。
2.打包测试
我们同样也可以把这些.o文件进行打包操作,形成一个文件
在静态库下我们用的打包操作是:ar -rc ,注意按照库的格式命名
查看打包库的情况:ar -tv
把打包的库文件和.h拷贝到该用户下,编译运行test.c
我们后发现报错了???这是为什么呢???
我们自己安装的属于第三方库,系统默认回去自己默认的路径去寻找,就不会找到这个库文件,虽然他们在同一路径下。我们需要指明库的路径和库名称,采用下面指令
gcc 文件 -L(跟路径) -l(跟库名称)
为什么要有库呢??测试目标文件生成之后,静态库就可以删掉了,程序照样可以正常运行
为什么要有库呢??
1.提高开发效率
2.隐藏源代码
二、动态库
同样还是上面的代码,我们继续测试动态库
1.正常测试
我们如果想要对动态库进行编辑,需要带上 -fPIC(产生位置无关码)选项
我们如果想对这些.o文件进行打包,我们需要借助-shared(动态格式)选项,对动态库打包不需要其他选项,直接使用gcc就可以
此时我们就可以正常对test.c进行编译。但是会报错
此时就与静态库相同,动态库也属于第三方库,需要指定库的路径和库名称
我们平时使用的库都是把.o文件和.h文件进行打包,上传到网络中,使用者将库下载下来,进阶捷报就可以正常操作了。
下面我们模拟一下这个过程
makefie中内容
libmyc.so:add.o myfile.ogcc -shared -o $@ $^
%.o:%.cgcc -c -fPIC $<.PHONY:clean
clean:rm -rf *.o libmyc.so mylib mylib.tgz.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp -rf *.h mylib/includecp -rf *.so mylib/libtar czf mylib.tgz mylib
2.安装测试
我们进行make output操作将相应的内容进行打包
用户把这个包下载下来,并且解压到自己的路径下,之后把这个压缩包删除就可以。
所谓的把库安装到系统中,本质就是把对应的文件拷贝到系统指定的路径中。
下面我们再次进行编译,我们可以发现报了一个这样的错误
头文件找不到,Linux下查找头文件会在当前路径和库对应的路径进行查找,我们的.h文件不在在下级路径下,系统自然就找不到。
我们需要用到-I(大写i)指定头文件路径,同时用-L(指定库路径)和-l(指定库名称)
3.运行测试
我们正常运行看一下
发现报错了??这是为什么呢??
编译时我们确定了编译环境所需要的路径以及一系列东西,但是对于运行程序的进程来说,并不知道库的路径(第三方库)。我们也可以用ldd查看链接了哪些库
我们要解决这个有四种方法 🌟直接把所使用的库拷贝到系统指定的路径下,一般是/usr/lib(sudo提权)
🌟使用环境变量LD_LINRARY_PATH,这个环境变量是指,操作系统查找库文件时候,除了去系统指定的目录去查找,同时也会去这个路径下查找
但是如果我们关掉机器,重新打开,这个环境变量就会消失。如果想让他一直存在,可以在跟目录下的_bash_profile和.bashrc修改即可🌟使用软链接的方式
🌟设置配置文件/etc/ld.so.conf.d
将库的路径放在这个目录中,目录名称必须以.conf结尾,之后使用ldconfig使配置生效
4.动态库&&静态库
🌟如果动态库和静态库同时存在,系统自动使用动态库,如果非要使用静态库,加-static选项
🌟如果我们所用的文件只存在静态库,系统将把这个链接静态库,其余正常链接静态库
🌟如果我们只提供动态库,非得想要静态链接,会报错
三、深入理解动态库
1.系统角度
运行代码,首先创建task_struct ,进程地址空间,将磁盘中test.c文件加载进内存,填写页表内容。动静态库在磁盘中也是一个个的文件,也要加载到内存,放在页表中,与物理内存建立映射。
🌟静态库:把test.c和libmyc.o一起加载到内存中,放在一起。运行时就不需要寻找库了。
🌟动态库:把test.c和libmyc.sof分别加载到内存中,其中动态库会被放在进程地址空间的共享区中。当调用这个库时,去共享区中查找,如果存在这个库,就跳转到共享库中调用。如果不存在就加载到内存中。如果其他文件要调用这个动态库,就直接去调用即可,不用再进行加载。动态库也叫做共享库,本质就是进程中代码和数据仅存在一份。补充: 1.进程地址空间的内容初始化是根据文件的代码数据进行填充的。
2.进程同样要对这些库进行管理,怎么管理呢??先描述,在组织
3.那些库加载了,那些库没有被加载,由操作系统自动完成。
2.编译角度
在磁盘中的文件中代码和数据在没有加载进入内存之前,也有自己对应的地址,数据和代码按照一定的格式进行存储。我们就可以用这个初始化我们进程的进程地址空间了。
编址方式有两种:绝对地址和相对地址,机器一般使用绝对编制的方式。
总结
以上就是今天要讲的内容,本文仅仅详细介绍了 。希望对大家的学习有所帮助,仅供参考 如有错误请大佬指点我会尽快去改正 欢迎大家来评论~~ 😘 😘 😘
相关文章:

动静态库(Linux)
文章目录 前言一、静态库二、动态库三、深入理解动态库总结 前言 我们之前用过c语言的库.Linux中默认的都是使用动态库,如果想要使用静态库,就必须加上-static选项。默认都是安装的动态库,系统中一般没有静态库,如果要使用&#…...
51单片机和ARM单片机的区别
在嵌入式系统设计与应用中,单片机作为核心控制单元,扮演着至关重要的角色。其中,51单片机和ARM单片机作为两种常见的单片机类型,各自具有独特的特点和优势。本文将从多个维度深入探讨这两种单片机的区别,以便读者更好地…...
[Day 81] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈在食品安全中的應用 前言 食品安全一直是全球關注的問題,隨著全球供應鏈的複雜性增加,追踪食品從生產到消費的過程變得愈發困難。區塊鏈技術以其去中心化、不可篡改的特性,為食品安全提供了可靠的解決方案。在這篇文章中,…...

flac格式怎么转mp3?关于flac转为MP3的方法介绍
flac格式怎么转mp3?MP3格式经过压缩,相较于flac文件,显著减小了文件体积。这一特点使得音乐的存储和传输更加便捷,尤其适合移动设备以及存储空间有限的场景。由于MP3文件体积较小,分享音乐变得非常简单,无论…...

【笔记】KaiOS 系统框架和应用结构(APP界面逻辑)
KaiOS系统框架 最早自下而上分成Gonk-Gecko-Gaia层,代码有同名的目录,现在已经不用这种称呼。 按照官网3.0的版本迭代介绍,2.5->3.0已经将系统更新成如下部分: 仅分为上层web应用和底层平台核心,通过WebAPIs连接上下层,这也是kaios系统升级变更较大的部分。 KaiOS P…...

java项目实现钉钉异常告警实时监控
最近有个小伙伴问我,我们的项目核心业务的地方总是有异常,虽然有打印日志,但不能立马通知我;所以今天我就教大家如何实现异常报警实时提醒 1.需要有钉钉 自己新建的企业用户 2.建一个群,需要有三人以上;…...

Spring Boot应用:电子商务平台开发
第2章 关键技术简介 2.1 Java技术 Java是一种非常常用的编程语言,在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中,Java的身影无处不在,并且拥有旺盛的生命力。Java的跨平台能力十分强大,只需一次编译…...
怎么在Vue3项目中引入Vant组件库并使用?
文章目录 前言一、项目中使用步骤1.安装:2.样式的导入(2种方法)2.1 main.ts全局导入(平常自己的项目用的这个全局)2.2 按需引入组件样式 (简单介绍一下)1.安装插件2.配置插件 3.组件按需使用:App.vue 总结 …...

springboot中有哪些方式可以解决跨域问题
文章目录 什么是跨域解决方案CrossOrigin注解实现WebMvcConfigurer接口CorsFilter过滤器如何选择? 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 Talk is cheap ࿰…...

Temporal Dynamic Quantization for Diffusion Models阅读
文章目录 AbstractIntroductionBackgrounds and Related Works2.1 扩散模型2.2 量化2.3 量化感知训练和训练后量化 TemporalDynamic Quantization3.1 量化方法3.2 扩散模型量化的挑战3.3 TDQ模块的实现3.4 工程细节时间步的频率编码TDQ模块的初始化 Experimental SetupResults5…...

828华为云征文|华为云Flexus X实例性能实测:速度与稳定性的完美结合
828华为云征文|华为云Flexus X实例性能实测:速度与稳定性的完美结合 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、实践环境介绍2.1 本次实践环境规划2.2 本次实践介绍 …...

【PyTorch】图像分割
图像分割是什么 Image Segmentation 将图像每一个像素分类 图像分割分类 超像素分割:少量超像素代替大量像素,常用于图像预处理语义分割:逐像素分类,无法区分个体实例分割:对个体目标进行分割全景分割:…...

如何快速建立自己的异地互联的远程视频监控系统,通过web浏览器可以直接查看公网上的监控视频(上)
目录 一、需求 二、方案 2.1、计划方案 2.2、实施准备 2.2.1所需配置的产品和服务 2.2.1.1云主机 (1)选择云平台 (2)配置云服务器 2.2.2.2视频监控平台软件 (1)视频监控平台软件 (2&am…...

实验2思科网院项目2.7.2-packet-tracer---configure-single-area-ospfv2---实践练习
实践练习 2.7.2-packet-tracer---configure-single-area-ospfv2---实践练习physical-mode 实验拓扑 相关设备配置 实验目标: 第 1 部分:构建网络并配置设备的基本设置 第 2 部分:配置和验证单区域 OSPFv2 的基本部署 第 3 部分:优化和验…...
Nginx实战经验分享:从小白到专家的成长历程!
目录 一、Nginx概述1、Nginx简介(1)事件驱动模型(2)异步处理(3)模块化设计(4)高性能(5)反向代理(6)负载均衡(7)…...
从画质设置看游戏引擎(其一)
前往我的博客,获取无广告,更好的阅读体验 1. 抗锯齿(Anti-Aliasing) 1.1 锯齿问题的起因 在三维模型的世界中,模型是连续的,但是屏幕像素是不连续,是离散的; 即当一个圆形显示在显…...

#git 问题failed to resolve head as a valid ref
问题如下: 解决方法: 1、运行 git fsck --full 可以查看具体error信息,一般都是head索引问题 2、.git\refs\heads\xxx(当前分支)txt编辑器打开显示乱码,而不是hash编码 3、在.git\logs\refs\heads\xxx&a…...

YOLOv11,地瓜RDK X5开发板,TROS端到端140FPS!
YOLOv11 Detect YOLOv11 Detect YOLO介绍性能数据 (简要) RDK X5 & RDK X5 Module 模型下载地址输入输出数据公版处理流程优化处理流程步骤参考 环境、项目准备导出为onnxPTQ方案量化转化使用hb_perf命令对bin模型进行可视化, hrt_model_exec命令检查bin模型的输入输出情况…...
Python精选200Tips:181-182
针对图像的经典卷积网络结构进化史及可视化 针对图像的经典卷积网络结构进化史及可视化(续)P181--MobileNet【2017】模型结构及创新性说明模型结构代码MobileNet V1版本MobileNet V2版本MobileNet V3 版本Small版本Large版本 P182--EfficientNet【2019】…...

SpringCloud 配置 feign.hystrix.enabled: true 不生效
SpringCloud 配置 feign.hystrix.enabled: true 不生效的原因 feign 启用 hystrix feign 默认没有启用 hystrix,添加配置,启用 hystrix feign.hystrix.enabledtrue application.yml 添加配置 feign:hystrix:enabled: true启用 hystrix 后,访…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...