进程动静态库

news2024/12/22 15:31:11

文章目录

    • 动态库和静态库
      • 1. 静态库
      • 2. 动态库

承接上文:
文件描述符

动态库和静态库

静态库与动态库:

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

1. 静态库

如果把我们提供的方法打包给别人用:

  1. 我们把源文件直接给别人
  2. 把我们的源文件想办法打包成库 = 库 + *.h

自己设计一个静态库:

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;
}

makefile:

lib=libmymath.a
$(lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.c
	gcc -c $^
.PHONY:clean
clean:
 rm -f *.o *.a

注:ar 是 gnu 归档工具,rc 表示 (replace and create)

在这里插入图片描述

生成的库其实也就是把所编译的 .o 文件打包为 .a 的库文件!!

如果要发布库文件,这时来修改一下makefile文件代码:

lib=libmymath.a
$(lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.c
	gcc -c $^
	
.PHONY:clean
clean:
	rm -rf *.o *.a output
	
.PHONY:output
output:
	mkdir -p lib/include
	mkdir -p lib/mymathlib
	cp *.h lib/include
	cp *.a lib/mymathlib

发布:

在这里插入图片描述

创建lib文件成功:

在这里插入图片描述

现在来使用一下这个打包好的库:

新建一个目录(当作是用户目录),拷贝一下lib目录到该目录:

在这里插入图片描述

那么该怎么使用这个库呢?

新建main.c文件:

//#include "lib/include/mymath.h"  //也可以这样用
#include "mymath.h"
int main()
{
    printf("1 + 1 = %d\n", add(1, 1));
    return 0;
}

写完c文件需要编译,但是如果我们直接编译是一定会报错的:

在这里插入图片描述

  • 系统找不到头文件!!!

这是就需要在指定目录中编译了:

这里以我的为例: gcc main.c -I ./lib/include/

在这里插入图片描述

  • 虽然编译依然还有报错,但已经不是头文件报错了。

报错提示找不到add函数,可以确定这里是链接式报错,主要是找不到add的实现方法。问题是还是找不到库的原因!!!

这是还需要再加一个指令条件: gcc main.c -I ./lib/include/ -L ./lib/mymathlib/

-L代表lib的首字母,表示让系统到 ./lib/mymathlib/ 这个目录中去查找add :

在这里插入图片描述

结果还是报错!!!!呜呜呜!!!

  • 原因还是因为: 不知道查找指定目录中的哪一个库,还需要指定库的名称:

指令: gcc main.c -I ./lib/include/ -L ./lib/mymathlib/ -l libmymath.a

其中 -l 表示 link 的意思

在这里插入图片描述

结果还是出错,这里需要注意一点,指定库名称时:

  • 要去掉前缀lib,要去掉后缀 .a,并且-l后要紧跟库名称,最好不要有空格

最终指令: gcc main.c -I ./lib/include/ -L ./lib/mymathlib/ -lmymath

在这里插入图片描述

最终,编译通过!!!

之所以使用 gcc 或 g++ 编译时,不需要加这些后缀,是因为其把lib库文件都安装到了系统目录中,可以直接识别到。

结论:

  1. 第三方库往后使用的时候,必定是要用gcc -l
  2. 深刻理解errno的本质
  3. 如果系统中只提供静态链接,则gcc只能对该库进行静态链接
  4. 如果系统中需要连接多个库,则gcc可以链接多个库

2. 动态库

先创建四个文件进行编写功能:

在这里插入图片描述

代码编写:

mylog.c

#include "mylog.h"
void Log(const char* info)
{
    printf("Warrning: %s\n", info);
}

mylog.h

#pragma once
#include <stdio.h>
void Log(const char *);

myprintf.h

#pragma once
#include <stdio.h>
void Print();

myprint.c

#include "myprint.h"
void Print()
{
    printf("hello new world\n");
    printf("hello solity\n");
    printf("hello pzh\n");
}

生成动态库编译选项:

  • shared: 表示生成共享库格式
  • fPIC :产生位置无关码(position independent code)
  • 库名规则:libxxx.so

生成动态库:

  • 编译 .o 文件指令:

  • gcc -fPIC -c myprint.c gcc -fPIC -c mylog.c

在这里插入图片描述

  1. 生成.so 动态库 : gcc -shared -o libmymethod.so *.o

在这里插入图片描述

​ 以so为后缀的文件就是生成的动态库了!!

打包静、动库文件:

makefile:

dy-lib=libmymethod.so
static-lib=libmymath.a

.PHONY:all
all:$(dy-lib) $(static-lib)

$(static-lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.c
	gcc -c $^

$(dy-lib):mylog.o myprint.o
	gcc -shared -o $@ $^
mylog.o:mylog.c
	gcc -fPIC -c $^
myprint.o:myprint.c
	gcc -fPIC -c $^

.PHONY:clean
clean:
	rm -rf *.o *.a *.so mylib 

.PHONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp *.h mylib/include
	cp *.a mylib/lib
	cp *.so mylib/lib

生成打包库文件:

在这里插入图片描述

使用库,这里专门进入一个空目录来调用动静态库查看效果:

先来使用一下静态库:

main.c代码:

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

指令: gcc main.c -I mylib/include/ -L mylib/lib -lmymath

在这里插入图片描述

更改main函数,调用动态库:

#include "mylog.h"
#include "myprint.h"
int main()
{
    Print();
    Log("hello log function");
    return 0;
}

跟静态库调用基本一样的指令: gcc main.c -I mylib/include/ -L mylib/lib -lmymethod

在这里插入图片描述

如果需要多种库就需要多种指明,如果需要同时调用动静态库,就需要如下指令:

gcc main.c -I mylib/include/ -L mylib/lib -lmymethod -lmymath

上面完全没问题,但是生成的可执行文件却执行不了:

在这里插入图片描述

那么此时应该如何加载动态库呢?

指令: sudo ln -s /home/solity/pzh/temp/test/mylib/lib/libmymethod.so /lib64/libmymethod.so

在这里插入图片描述

这里使用的是绝对路径,可以参考我当前的路径对照,进行修改为自己的路径:

在这里插入图片描述

此时,便大功告成了:

在这里插入图片描述

测试完成后,不要忘记删除刚刚创建的临时软链接库: sudo unlink /lib64/libmymethod.so

解决加载找不到动态库的方法:

  1. 拷贝到系统默认的库路径:/lib/user/lib64 (强烈推荐,性价比高)

  2. 在系统默认的库路径/lib/user/lib64下建立软连接

  3. 将自己库所在的路径,添加到系统的环境变量LD_LIBRARY_PATH中(默认是没有的,如果有可能是因为其他原因系统默认添加了)

    在这里插入图片描述

    然后将路径添加:

    先来查看:

    在这里插入图片描述

    我这里是因为配置过vim自动添加的,默认是没有的!!

    添加指令: export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:/home/solity/pzh/temp/test/mylib/lib

    后面的路径自己系统文件下的绝对路径:

    在这里插入图片描述

    对比上图,这里的动态库路径已经有了!!
    在这里插入图片描述

    这里就可以直接 ./a.out就可以直接运行了。

  4. ldconfig 配置: /etc/ld.so.conf.d 建立自己的动态库路径配置文件,然后重新ldconfig更新即可

    先进入该目录: cd /etc/ld.so.conf.d (注意:这里使用root用户进行操作)

    在这里插入图片描述

    这些配置文件里面放的都是路径。

    然后我们来新建一个conf文件:
    在这里插入图片描述

    将动态库的路径放到里面,保存退出!!

    然后再进行使用指令 : ldconfig 加载一下

    在这里插入图片描述
    此时就完成了:
    在这里插入图片描述

    这是来清空一下配置文件,重新加载:

    在这里插入图片描述

    可以看到刚才还有的路径,再次查看就已经没有了!!!

    注意: 如果添加了配置文件,将不会随着关机重启而还原,配置文件一旦添加将永久拥有,除非自己删除!!

实际情况,我们用的库都是别人的成熟的库,都采用直接安装到系统的方式!!!

动态库再进程运行的时候,是要被加载的(静态库没有)。常见的动态库被所有的可执行程序(动态链接的)都要使用,动态库 ——— 共享库

所以 动态库在系统中加载之后,会被所有进程共享

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ISP比普通的静态代理相比有什么优势?

ISP&#xff08;Internet Service Provider&#xff09;&#xff0c;即互联网服务提供商&#xff0c;是向广大用户综合提供互联网接入业务、信息业务、增值业务的电信运营商。而静态代理则是一个固定不变的代理IP地址&#xff0c;具有稳定性强、兼容性好和管理方便等特点。当我…

上位机图像处理和嵌入式模块部署(树莓派4b之自动化测试)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 硬件、软件功能开发ok只是产品开发的第一步。怎么做到自动化测试、保证产品质量才是关键。很多时候&#xff0c;我们给客户提供了功能&#xff0c;…

适用于集成温度补偿晶体振荡器SG3225EEN

在现代电子系统中&#xff0c;随着技术的发展&#xff0c;对晶体振荡器的要求越来越高。例如&#xff0c;人工智能、5G等技术的应用需要更高的频率稳定度和更低的相位噪声&#xff0c;以确保数据传输的准确性和系统的高效运行。此外&#xff0c;随着电子设备向智能化、小型化发…

PHP+MYSQL多条件选一通用搜索系统功能单文件7KB

通用功能: 快速填写参数用于自己的mysql数据表搜索,ajax载入数据 <?php header("content-Type: text/html; charsetUTF-8"); //error_reporting(0);$dbhost "localhost"; //数据库地址本地localhost $dbuser "chalidecom"; //数据库账号 …

C语言扫雷游戏完整实现(下)

文章目录 前言一、排雷函数菜单二、排雷函数菜单的实现三、拓展棋盘功能四、源码1. test.c源文件2. game.h头文件3. game.c源文件 总结 前言 C语言实现扫雷游戏的排雷菜单&#xff0c;以及功能的实现&#xff0c;拓展棋盘功能&#xff0c;以及源码等。 上半部分的链接地址: C语…

第一篇【传奇开心果系列】Python深度学习库技术点案例示例:深度解读深度学习在自动驾驶领域的应用

传奇开心果博文系列 系列博文目录Python深度学习库技术点案例示例系列 博文目录前言一、深度学习在自动驾驶方面的应用介绍二、目标检测和识别示例代码三、路况感知示例代码四、行为预测示例代码五、路径规划示例代码六、自动驾驶控制示例代码七、感知融合示例代码八、高精度地…

PyCharm开发工具安装plugins插件

一. 简介 通过前面的学习&#xff0c;我们知道 python开发常用的一个开发工具&#xff08;即IDE&#xff09;是 PyCharm。 本文来简单介绍一下&#xff0c;PyCharm开发工具是如何安装 plugins插件的。其实与 vscode软件安装插件类似。 本文来学习 PyCharm开发工具安装一个中…

51.HarmonyOS鸿蒙系统 App(ArkUI)通知

普通文本通知测试 长文本通知测试 多行文本通知测试 图片通知测试 进度条通知测试 通知简介 应用可以通过通知接口发送通知消息&#xff0c;终端用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用。 通知常见的使用场景&#xff1a; 显示接收到的短消息、…

正则表达式.java

正则表达式的作用&#xff1a; ①可以校验字符串是否满足一定的规则&#xff0c;并用来校验数据格式的合法性&#x1f9f8; &#x1f9e9;[]:只能是括号里的字符 &#x1f9e9;[^]&#xff1a;除了括号里的字符 &#x1f9e9;[- -]:表示两段范围&#xff0c;满足其一即可 &a…

openstack-镜像封装 7

再克隆两台主机并且安装图形化组件和虚拟化组件 进入图形化界面并安装一个虚拟化管理器 根下创建一个目录&#xff0c;虚拟化管理器新添加一个路径 创建虚拟化 配置虚拟化主机 设置虚拟化主机配置 安装所需软件 清理创建云主机时安装的组件 主机安装虚拟化工具 清理虚拟化缓存 …

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段&#xff0c;通过对LED的发光磷粉进行LED背光进行技术革新&#xff0c;可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线&#xff0c;从硬件的角度解决了蓝光危害眼睛的问题&#…

深入探究音视频开源库WebRTC中NetEQ音频抗网络延时与抗丢包的实现机制

目录 1、引言 2、WebRTC简介 3、什么是NetEQ&#xff1f; 4、NetEQ技术详解 4.1、NetEQ概述 4.2、抖动消除技术 4.3、丢包补偿技术 4.4、NetEQ概要设计 4.5、NetEQ的命令机制 4.6、NetEQ的播放机制 4.7、MCU的控制机制 4.8、DSP的算法处理 4.9、DSP算法的模拟测试…

基于Flask的岗位就业可视化系统(三)

前言 本项目综合了基本数据分析的流程&#xff0c;包括数据采集&#xff08;爬虫&#xff09;、数据清洗、数据存储、数据前后端可视化等 推荐阅读顺序为&#xff1a;数据采集——>数据清洗——>数据库存储——>基于Flask的前后端交互&#xff0c;有问题的话可以留言…

unity学习(87)——断线的原因--客户端堆栈溢出1

无论unity还是exe问题都是一样的&#xff0c;都是客户端一直在发123&#xff0c;但收不到124&#xff0c;退出时服务器能发126&#xff0c;但是客户端压根接受不到126。一下确实解决不了问题&#xff0c;但其实已经十分接近了&#xff01; 客户端断线后就再也收不到任何包了&a…

ElasticSearch批处理

在刚才的新增当中&#xff0c;我们是一次新增一条数据。那么如果你将来的数据库里有数千上万的数据&#xff0c;你一次新增一个&#xff0c;那得多麻烦。所以我们还要学习一下批量导入功能。 也就是说批量的把数据库的数据写入索引库。那这里的需求是&#xff0c;首先利用mybat…

ctfshow web41-web50

web41 代码审计 <?php if(isset($_POST[c])){$c $_POST[c]; if(!preg_match(/[0-9]|[a-z]|\^|\|\~|\$|\[|\]|\{|\}|\&|\-/i, $c)){eval("echo($c);");} }else{highlight_file(__FILE__); } ?> 过滤了&#xff1a;[0-9] [a-z] ^ ~ $ [ ] { } & -…

用户中心 -- 代码理解

一、删除表 & if 删除表 1.1 DROP TABLE IF EXISTS user 和 DROP TABLE user 网址&#xff1a; 用户管理第2节课 -- idea 2023.2 创建表--【本人】-CSDN博客 二、 代码 2.1 清空表中数据 的 命令 【truncate 清空】 网址&#xff1a; 用户管理第2节课 -- idea 2…

云原生Kubernetes: K8S 1.29版本 部署GitLab

目录 一、实验 1.环境 2.搭建NFS 3.K8S 1.29版本 部署Redis 4.K8S 1.29版本 部署Postgresql 5.K8S 1.29版本 部署GitLab 6.K8S 部署istio微服务 7.K8S 部署ingress应用路由 二、问题 1.K8S部署gitlab报错 2.gitlab创建失败 3.生成网关资源报错 4.安装istio 报错 …

Powershell 一键安装 virtio_qemu_agent

前言 qemu-guest-agent qemu-guest-agent是一个助手守护进程,安装在客户机中。它用于在主机和客户端之间交换信息,并在客户端执行命令。 在Proxmox VE中,qemu-guest-agent主要用于三件事: 正确关闭客户机,而不是依赖于ACPI命令或windows策略在进行备份/快照时冻结客户机…

中小型企业网络实战topo

1、设备命名&#xff0c;务必按照规范进行命名规划&#xff1b; 2、子网划分&#xff0c;申请到了公网地址段&#xff0c;201.1.1.0/24&#xff0c;根据公司的实际情况&#xff0c;合理规划拓扑需要的公网地址&#xff0c; 做到合理规划不浪费&#xff1b; 3、子网划分&a…