【Linux】静态库与动态库制作及运行原理

这篇具有很好参考价值的文章主要介绍了【Linux】静态库与动态库制作及运行原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。


【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

0. 静态库与动态库

先来总体描述下静态库与动态库的区别.

静态库是将头文件总体复制到可执行文件当中动态库是在可执行程序运行时进行了动态链接(所需要某个实现方法就去内存中查找).

所以静态链接所形成的可执行文件可以在没有相关配置的设备上运行,而动态链接的可执行程序对设备环境要求较高.

通常情况下,我们将自己的代码提供给别人使用时,往往只会提供: 头文件与源码打包成的库.这个库可以是动态链接也可以是静态链接.

  • 总结:动静态库都为将形成的二进制码进行链接的过程,二者区别仅为链接方式不同

1. 制作与使用静态库

接下来介绍如何制作一个自己的静态链接库.

我们先正常进行一段编码.分别编写头文件.h与方法.c

// .h编写
#pragma once
int add(int x,int y);
// .c编写
extern int myerrno;

int add(int x,int y)
{
    return x+y;
}

我们先使用如下指令对.c进行编译

gcc -c myadd.c
# 该指令会自动生成.c同名的.o文件

接下里就是对myadd.o进行链接的过程

我们使用ar工具带上rc选项来进行链接,具体指令如下

静态链接库的文件名格式为 libxxx.a

ar -rc libmyadd.a myadd.o

此时就编译完成了我们所需要的静态库.

现在我们试试写一段代码去引用下我们的方法.

#include "myadd.h"
#include<stdio.h>
int main()
{
    printf("%d\n",add(1,2));
    return 0;
}

接下来我们试着用gcc进行编译运行看看

gcc -o test test.c

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

显示其不认识我们的add函数,但是我们不是将头文件包含了嘛?

这是因为gcc编译时会去特定的路径下查找头文件与库文件信息.

该目录结构一般如下

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

在lib/include路径下存放我们自定义的头文件 在lib/myaddlib存放我们打包生成好的库文件.

之后,手动指定gcc去哪里寻找对应的链接文件

gcc -o test test.c -I lib/include -L lib/myaddlib -lmyadd

其中 -I表示头文件在哪个路径下 -L表示链接文件在哪个路径下 -l表示具体是哪个链接文件的路径(此时要去掉前缀lib去掉后缀.a)

为什么头文件不需要指定名称了呢?因为我们在代码中已经手动include "头文件"了

那么为什么我们平常使用时没有这么麻烦呢?

因为系统在安装库时,把所有需要的文件放在了指定目录下,gcc编译时会自己去该目录进行寻找,我们仅需要制定形成的链接文件即可

头文件存储在 /usr/include中 形成的链接文件放在/lib64下

我们试试将我们的东西软连接到对应目录下

sudo ln -s $(pwd)/lib/include /usr/include/lib

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

sudo ln -s $(pwd)/lib/myaddlib/libmyadd.c /lib64/libmyadd.c

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

此时我们直接带上-l选项即可完成编译

gcc -o test test.c  -lmyadd

这也为安装静态库的方法,我们可以通过复制/软链接到对应的目录

在编译完成后该文件即可独立运行,此时将编译时所依赖文件全部删除也不影响该程序运行

makefile:

lib=libmyadd.a

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

.PHONY:clean
clean:
	rm -rf *.o lib *.a test *.a*
	
.PHONY:output
output:
	mkdir -p ./lib/include
	mkdir -p ./lib/myaddlib/
	cp *h ./lib/include
	cp *a ./lib/myaddlib

2. 制作与使用动态库

先来介绍一个指令: ldd + 可执行文件

可以列出当前文件运行时所需的动态库目录,例如我们刚刚使用的test

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

为了方便介绍,我们将多个方法.c文件打包成一个动态库文件

// myPrintf.h
#pragma once
#include <stdio.h>
void Printf();
// myLog.h
#pragma once
#include <stdio.h>
void Log();
// myPrintf.c
void Printf()
{
    printf("hello myprintf\n");
}
// myLog.c
void Log()
{
    printf("hello mylog\n");
}

将其进行编译成二进制文件

gcc -fpic -c myPrintf.c myLog.c

fpic为与位置无关码

将其进行链接

gcc -shared -o libmyfunc.so myPrintf.o myLog.o 

动态库的后缀为so,前缀为lib

此时一个名为 libmyfunc.so的可执行文件就被编译生成了.(至于为什么是可执行的我们之后再说)

为了规范 我们将其放进如下目录

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

同样编写一段代码尝试使用

// test.c
#include "./lib/include/myLog.h"
#include "./lib/include/myPrintf.h"
int main()
{
    Printf();
    Log();
    return 0;
}

编译指令与静态库相似

 gcc -o mytest test.c -I ./lib/include -L ./lib/lib -lmyfunc

但是,此时我们直接运行会发现.

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

原因:动态库并不会将自己的库文件放进可执行程序,其运行时动态在内存中进行查找.而我们上面仅告诉了编译器我们的动态库在哪,而加载器并不知道,所以找不到

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

  • 方法也是将自己的动态库文件拷贝/软连接到/lib下

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

  • 一个方法是修改/etc/ld.so.conf.d下的文件内容

在该目录下创建一个.conf结尾的文件,将动态库所在的文件目录路径填入即可【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

sudo ldconfig
  • 还有一个方法是导入环境遍历 LD_LIBRARY_PATH后面带上上文的路径即可

3. 动态库是如何被加载到内存?

3.1程序地址空间

在文件被编译编程成可执行程序时,会有一套自己的内部地址.与PCB私有的栈帧模型类似

将代码放在了代码区,只读变量放在了只读变量区等…

他私有的地址,当其放入内存时,就有物理地址自动与其一一对应

【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维

当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.

动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.

多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝

函数内部调用会跳转到函数的虚拟地址.

若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.

这就是动态库编译选项中与位置无关码FPIC的含义

当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.

动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.

多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝

函数内部调用会跳转到函数的虚拟地址.

若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.

这就是动态库编译选项中与位置无关码FPIC的含义
【Linux】静态库与动态库制作及运行原理,Linux,linux,java,restful,服务器,运维文章来源地址https://www.toymoban.com/news/detail-754281.html

到了这里,关于【Linux】静态库与动态库制作及运行原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解Linux中的动态库与静态库

                                                      🎬慕斯主页 : 修仙—别有洞天                                                 ♈️ 今日夜电波:I Wish My Mind Would Shut Up—Ivoris                                                          

    2024年01月24日
    浏览(40)
  • 如何在linux下制作静态库和动态库

    静态库顾名思义是静态的,即程序编译链接时,会把静态库的代码链接到可执行文件中。运行时不需要静态库(将静态库删了也能运行)。 相当于静态库的代码复制到了可执行文件中。 分别有如下add.c add.h sub.c sub.h四个文件格式。 首先把.c文件都编译成.o文件。使用下面命令

    2024年01月24日
    浏览(36)
  • 【Linux从入门到精通】动静态库的原理与制作详解

         本篇文章主要是 围绕动静态库的原理与制作进行展开讲解 的。其中涉及到了 inode的概念引入和软硬连接 的讲解。会结合实际操作对这些抽象的概念进行解释,希望会对你有所帮助。 文章目录 一、inode 概念 二、软硬链接 2、1 软连接 2、2 硬链接 三、动静态库概念 3、

    2024年02月12日
    浏览(28)
  • 动态库与静态库

    动态库(Dynamic Library)和静态库(Static Library)是软件开发中常用的两种库文件形式。 动态库:是一组共享的目标代码文件,它们在运行时动态链接到应用程序中。动态库在系统中独立存在,可以被多个应用程序共享。当应用程序运行时,操作系统会加载动态库,并在需要时

    2024年02月08日
    浏览(25)
  • 静态链接库与动态链接库

    由于计算机无法直接理解和执行高级语言(C、C++、Java)程序,需要将 高级语言程序 转换为 机器语言程序 (机器语言是用二进制代码表示的、计算机唯一可以直接识别和执行的一种机器指令的集合),通常把这种转换过程叫做 翻译 。 在C/C++中,整个翻译过程可以分为四步

    2024年02月04日
    浏览(34)
  • 【计算机网络】 静态库与动态库

    库有两种:静态库(.a、.lib)和动态库(.so、.dll)。所谓静态、动态是指链接。静态库是将整个库文件都拷贝到可执行文件中了,而动态库只是将索引文件拷贝到可执行文件中,可以通过索引文件找到动态库文件。 静态库实践 使用方法 首先我们用vs创建一个静态库,再创建

    2024年02月09日
    浏览(37)
  • CMake构建静态库与动态库以及使用

    用例子的方式通俗易懂地解释CMake构建静态库与动态库的过程。 任务: 建立一个静态库和动态库,提供HelloFunc 函数供其他程序编程使用,HelloFunc向终端输出Hello World 字符串。 安装头文件与共享库。 编写一个程序去使用构建的共享库。 (1)建立 t3 目录,用于存放本节涉及到

    2024年02月07日
    浏览(27)
  • 【Linux】CentOS制作Java+GDAL环境镜像并部署运行SpringBoot项目

    环境部署是一个非常繁琐又耗时的工作,尤其是涉及更换操作系统时,其难度更是成倍的增加。本文通过构建起软件运行镜像,并将SpringBoot项目运行在容器中,以期减小软件部署工作所投入的时间与精力。 在Windows环境下构建了一个SpringBoot项目,涉及对MySQL数据库、PostgreSQ

    2024年02月11日
    浏览(34)
  • .NET Native AOT的静态库与动态库

    .NET不仅可以使用 C静态库与动态库,也可以将.NET实现的函数导出为C静态库与动态库。在没有Native Aot之前,.NET只能通过P/Invoke享受C/C++生态,而在Native Aot之后,不仅可以享受这些生态,还可以开发SDK供其他语言调用。 .NET Native AOT的NativeLib参数用于指定本机库的类型。在.NET

    2024年02月16日
    浏览(25)
  • VS2019静态库与动态库入门操作指南

    源代码的二进制文件; 分为动态编译与静态编译; 1)区别 (1)动态编译不便于发布,静态编译便于发布; (2)动态编译生成的可执行文件体积较小,静态生成的可执行文件体积较大。 ​ Windows中静态库后缀为.lib 动态库后缀为.dll ​ Linux中静态库后缀为.a 动态库后缀为.

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包