动静态库(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.编译角度
在磁盘中的文件中代码和数据在没有加载进入内存之前,也有自己对应的地址,数据和代码按照一定的格式进行存储。我们就可以用这个初始化我们进程的进程地址空间了。
编址方式有两种:绝对地址和相对地址,机器一般使用绝对编制的方式。

总结

以上就是今天要讲的内容,本文仅仅详细介绍了 。希望对大家的学习有所帮助,仅供参考 如有错误请大佬指点我会尽快去改正 欢迎大家来评论~~ 😘 😘 😘

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

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

相关文章

注册安全分析报告:闪送

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

用户态缓存:链式缓冲区(Chain Buffer)

目录 链式缓冲区&#xff08;Chain Buffer&#xff09;简介 为什么选择链式缓冲区&#xff1f; 代码解析 1. 头文件与类型定义 2. 结构体定义 3. 宏定义与常量 4. 环形缓冲区的基本操作 5. 其他辅助函数 6. 数据读写操作的详细实现 7. 总结 8. 结合之前的内容 9. 具…

C~排序算法

在C/C中&#xff0c;有多种排序算法可供选择&#xff0c;每种算法都有其特定的应用场景和特点。下面介绍几种常用的排序算法&#xff0c;包括冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序&#xff0c;并给出相应的示例代码和解释。 冒泡排序&#xff08;Bubble …

LeetCode142. 环形链表 II(2024秋季每日一题 28)

给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数…

Android studio配置AVD虚拟机

目录 设置虚拟设备参数 安装HAXM 找到HAXM安装包 安装 启动虚拟设备 设置虚拟设备参数 Tools->Devices Manager->Add a new divece一个加号符号的图标->Create Virtual Device 选择尺寸参数&#xff0c;没有合适的话选择New Hardware Profile&#xff0c;调整好…

【深度学习】【TensorRT】【C++】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【TensorRT】【C】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【TensorRT】【C】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转engineWindows平台搭…

中国空间计算产业链发展分析

2024中国空间计算产业链拆解 空间计算设备主要包括AR、VR、MR等终端设备。VR设备通常包括头戴式显示器&#xff08;VR头盔&#xff09;、手柄或追踪器等组件&#xff0c;用以完全封闭用户视野&#xff0c;营造虚拟环境体验。这些设备配备高分辨率显示屏、内置传感器和跟踪器。 …

【Spring】Spring Aop基础入门

一、AOP(Aspect-Oriented Programming: 面向切面编程) 将那些与业务无关&#xff0c;却为业务模块所共同调用的逻辑&#xff08;例如事务处理、日志管理、权限控制等&#xff09;封装抽取成一个可重用的模块&#xff0c;这个模块被命名为“切面”&#xff08;Aspect&#xff09…

怎么备考2024年11月软考高级系统架构师 ?

分享下我的系统架构设计师考证之路&#xff0c;希望能对即将参加考试的小伙伴们带来一些启示和帮助。 先贴出自己软考系统架构设计师成绩&#xff0c;备考一次就通过了考试。 一、架构考试教材 架构考试教材目前使用的是系统架构设计师教程&#xff08;第2版&#xff09;&…

将数字化转型理论应用于实践的路径:企业数字化转型的落地方案

将数字化转型理论应用于实践的路径 随着数字化技术的飞速发展&#xff0c;越来越多的企业开始意识到&#xff0c;成功的数字化转型不仅仅是引入新技术&#xff0c;更是如何将理论与实践相结合&#xff0c;实现企业业务流程的根本性变革。数字化转型不仅意味着技术上的革新&…

宝塔面板部署雷池社区版教程

宝塔面板部署雷池社区版教程 简单介绍一下宝塔面板&#xff0c;安全高效的服务器运维面板&#xff0c;使用宝塔面板的人非常多 在网站管理上&#xff0c;许多用户都是通过宝塔面板进行管理&#xff0c;宝塔面板的Nginx默认监听端口为80和443&#xff0c;这就导致共存部署时雷池…

《面向对象是怎样工作的》笔记

6、1、在面向对象的世界中&#xff0c;我们需要事先为所有的行动准备好方法并通过消息传递来调用方法&#xff0c;这样事物才会开始运作。 2、实际上&#xff0c;类、继承和多态应该被明确定义为能提高软件的可维护性和可重用行的结构。类将变量和子程序汇总在一起&#xff0c…

单片机的两种看门狗原理解析——IWDG和WWDG

一、IWDG独立开门狗的主要性能 计时机制&#xff1a; 递减计数器 独立开门狗的初始频率&#xff1a; LSI低速内部时钟&#xff1a;RC震荡器&#xff0c;40kHz 独立开门狗是以LSI为初始频率的&#xff0c;所以独立开门狗的初始时钟频率取决与单片机本身&#xff0c;因此在使…

AES CCM详解

AES CCM是一种对数据进行加密及完整性检查的算法&#xff0c;主要用到AES中的CBC(完整性检查)和CTR(对明文进行加密)&#xff0c;除此之外&#xff0c;还涉及到对数据的格式化(本文着重阐述)。 文章目录 加密过程STEPS 解密及校验过程STEPS 格式化B0的构成B0解析举例AAD的格式化…

David律所代理Beau Parsons的小狗插画图案版权维权,速排查下架

案件基本情况&#xff1a;起诉时间&#xff1a;2024-9-16案件号&#xff1a;2024-cv-08505原告&#xff1a;Beau Parsons原告律所&#xff1a;David起诉地&#xff1a;伊利诺伊州北部法院涉案商标/版权&#xff1a;原告品牌简介&#xff1a;Beau Parsons是一位来自澳大利亚的专…

C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍

文章目录 前言一、list二、list类的初始化和尾插三、list的迭代器的基本实现四、list的完整实现五、测试六、整个list类总结 前言 C模拟实现list&#xff1a;list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍 一、list list本…

[Linux]从零开始的Minecraft服务器搭建教程

一、前言 学习Linux有一段时间了&#xff0c;当然&#xff0c;我们要把学习的知识运用到实际生活中去。最近朋友们都在玩我的世界&#xff0c;网易版的我的世界联机非常不稳定&#xff0c;用起来也算是非常难受了。所以还是准备转战JAVA版。为了联机&#xff0c;可以考虑一个人…

计算机网络 --- Socket 编程

序言 在上一篇文章中&#xff0c;我们介绍了 协议&#xff0c;协议就是一种约定&#xff0c;规范了双方通信需要遵循的规则、格式和流程&#xff0c;以确保信息能够被准确地传递、接收和理解。  在这篇文章中我们将介绍怎么进行跨网络数据传输&#xff0c;在这一过程中相信大家…

CSS调整背景

一、设置背景颜色 通过 background-color 属性指定&#xff0c;值可以是十六进制 #ffffff&#xff0c;也可以是rgb(0, 255, 255)&#xff0c;或是颜色名称 "red" div {background-color: red; /* 通过颜色名称设置 */background-color: #ff0000; /* 通过十六进制设…

图像分割(九)—— Mask Transfiner for High-Quality Instance Segmentation

Mask Transfiner for High-Quality Instance Segmentation Abstract1. Intrudouction3. Mask Transfiner3.1. Incoherent Regions3.2. Quadtree for Mask RefinementDetection of Incoherent Regions四叉树的定义与构建四叉树的细化四叉树的传播 3.3. Mask Transfiner Architec…