进程动静态库

文章目录

    • 动态库和静态库
      • 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.mfbz.cn/a/571551.html

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

相关文章

python绘制R控制图(Range Chart)

R控制图&#xff08;Range Chart&#xff09;&#xff0c;也称为范围图或移动极差图&#xff0c;是一种用于分析和控制生产过程中的变异性的统计工具。它通常与Xbar控制图&#xff08;均值图&#xff09;一起使用&#xff0c;可以提供关于生产过程变异性的额外信息。以下是R控制…

ArgoCD集成部署到Kubernetes

1&#xff1a;环境 kubernetes1.23.3ArgoCD2.3.3 2&#xff1a;ArgoCD介绍 Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. Argo CD是一个基于Kubernetes的声明式的GitOps工具。 那么&#xff0c;什么是GitOps呢&#xff1f; GitOps是以Git为基…

feign整合sentinel做降级知识点

1&#xff0c;配置依赖 <!-- Feign远程调用依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency> <!--sentinel--><dependency>…

Linux使用操作(一)

Linux创建链接的方式 在Linux中&#xff0c;可以给文件创建链接。链接的意思可以理解是快捷方式&#xff0c;它指向另一个文件或目录。 软链接 软连接&#xff08;也叫符号链接&#xff09;是一种特殊类型的文件&#xff0c;它指向另一个文件或目录 语法 ln -s 原文件路径…

谷歌发布基于声学建模的无限虚拟房间增强现实鲁棒语音识别技术

声学室模拟允许在AR眼镜上以最少的真实数据进行训练&#xff0c;用于开发鲁棒的语音识别声音分离模型。 随着增强现实&#xff08;AR&#xff09;技术的强大和广泛应用&#xff0c;它能应用到各种日常情境中。我们对AR技术的潜能感到兴奋&#xff0c;并持续不断地开发和测试新…

SpringBoot---------整合Mybatisplus

快速入门 第一步&#xff1a;导入依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency> 第二步&#xff1a;编写mapper…

区块链 | OpenSea 相关论文:Toward Achieving Anonymous NFT Trading(下)

&#x1f951;原文&#xff1a; Toward Achieving Anonymous NFT Trading VII 讨论&#xff1a;关于匿名性与市场平台的困境 在本文的这一部分&#xff0c;我们将讨论关于隐藏 NFT 所有者地址的困境&#xff0c;以及为什么像 OpenSea 这样的 NFT 市场平台几乎必须得到完全的信…

Java | 选择排序算法实现

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;实现选择排序算法。程序需要能够接收一个整型数组作为输入&#xff0c;并输出排序后的数组。 选择排序是一种简单直观的排序算法&#xf…

imx6ull -- SPI

SPI 是 Motorola 公司推出的一种同步串行接口 技术&#xff0c;是一种高速、全双工的同步通信总线&#xff0c; SPI 时钟频率相比 I2C 要高很多&#xff0c;最高可以工作 在上百 MHz。 SPI 以主从方式工作&#xff0c;通常是有一个主设备和一个或多个从设备&#xff0c;一般 SP…

ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件

前言&#xff1a; 从开始学习Vue到使用element-ui-admin已经有将近快两年的时间了&#xff0c;在之前的开发中使用element-ui上传组件el-upload都是直接使用文件选取后立即选择上传&#xff0c;今天刚好做了一个和之前类似的文件选择上传的需求&#xff0c;不过这次是需要手动点…

[InternLM训练营第二期笔记]5. LMDeploy 量化部署 LLM 实践

该系列是上海AI Lab举行的书生 浦语大模型训练营的相关笔记部分。 该笔记是第五节课&#xff0c;学习大语言模型量化的基本概念&#xff0c;以及利用LMDeploy工具进行微调。 0. 模型部署的概念 0.0 背景 如果要将大模型在特定平台&#xff08;大到服务器集群&#xff0c;小到…

需求 分析

需求分析的任务 需求分析的任务 1、需求分析是软件定义时期的最后一个阶段&#xff0c;它的基本任务是准确地回答“系统必须做什么?”这个问题。 2、确定系统必须完成哪些工作&#xff0c;也就是对目标系统提出完整、准确、清晰、具体的要求。 3、系统分析员应该写出软件需求…

Docker网络及CPU资源控制

一、实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容…

Gradio 最快创建Web 界面部署到服务器并演示机器学习模型,本文提供教学案例以及部署方法,避免使用繁琐的django

最近学习hugging face里面的物体检测模型&#xff0c;发现一个方便快捷的工具&#xff01; Gradio 是通过友好的 Web 界面演示机器学习模型的最快方式&#xff0c;以便任何人都可以在任何地方使用它&#xff01; 一、核心优势&#xff1a; 使用这个开发这种演示机器学习模型的…

【C++题解】1302. 是否适合晨练?

问题&#xff1a;1302. 是否适合晨练&#xff1f; 类型&#xff1a;分支 题目描述&#xff1a; 夏天到了&#xff0c;气温太高&#xff0c;小明的爷爷每天有晨练的习惯&#xff0c;但有时候温度不适合晨练&#xff1b;小明想编写一个程序&#xff0c;帮助爷爷判断温度是否适合…

5分钟——测试搭建的springboot接口(二)

5分钟——测试搭建的springboot接口&#xff08;二&#xff09; 1. 查看数据库字段2. 测试getAll接口3. 测试add接口4. 测试update接口5. 测试deleteById接口 1. 查看数据库字段 2. 测试getAll接口 3. 测试add接口 4. 测试update接口 5. 测试deleteById接口

计算机网络-IS-IS基础配置实验

前面我们了解了IS-IS的一些基础理论&#xff0c;从建立邻接、链路状态数据库同步以及路由计算&#xff0c;现在开始学习下配置操作。 一、IS-IS配置 网络拓扑图&#xff1a; 拓扑图 IS-IS有Level级别的区分&#xff0c;Level-1可以是性能较低的设备只维护区域内的LSDB&#xff…

论文辅助笔记:LLM-MOB代码解读

论文笔记 Where Would I Go Next? Large Language Models as Human Mobility Predictor-CSDN博客 1 主函数 1.1 导入库 import os import pickle import time import ast import logging from datetime import datetime import pandas as pd from openai import OpenAIclie…

Sqli-labs靶场第25关[Sqli-labs-less-25]自动化注入-SQLmap工具注入

过滤了AND OR 使用的函数是 preg_replace 特点&#xff1a;只对值进行一次检测闭合方式为 单引号 可以使用双写进行绕过 手工注入 ?id0 union select 1,database(),user() -- sqlmap自动化注入 sqlmap.py -u http://192.168.58.114:802/sqli-labs/Less-25/?id2 --batch -…

Aurora-64B/10B、XDMA与DDR结合设计高速数据流通路设计/Aurora光纤设计/XDMA读取DDR设计/基于FPGA的高速数据传输设计

因最近想通过FPGA把数据从光纤传到PC&#xff0c;借此机会和大家一起学习Aurora、XDMA结合DDR 制作不易&#xff0c;记得三连哦&#xff0c;给我动力&#xff0c;持续更新&#xff01;&#xff01;&#xff01; 完整工程文件下载&#xff1a;XDMA读写DDR工程 提取码&…