您当前的位置:首页 > 电脑百科 > 软件技术 > 操作系统 > linux百科

Linux 下静态链接和动态链接的原理及应用

时间:2023-03-04 13:38:51  来源:今日头条  作者:Linux码农

我们知道一个.c 文件经过编译、链接最终可以形成一个可执行文件。

链接原理

当我们的程序包含多个文件时,那么这些文件是怎么形成一个目标文件的呢?

这就要涉及到链接器。

链接器的作用就是将多个目标文件链接成一个完整、可加载、可执行的目标文件。其输入是一组可以重定位的目标文件。

链接的主要作用有2个:

符号解析:将目标文件内的引用符号和该符号的定义联系起来。

将符号定义与存储器的位置联系起来,修改对这些符号的引用。

 

目标文件

典型的目标文件有3种形式

可重定位目标文件:这种目标文件后缀通常为.o,这种文件包含已经转换成机器指令的二进制代码和数据,但是这种文件还不能直接执行,因为这些指令和数据中往往还引用其他模块(目标文件)中的符号,这些其他模块的符号对于本模块来讲还都是未知的,因此这些符号的解析需要链接器对这些模块进行连接,这种操作也称为“重定位”。

可执行目标文件:这种文件同样包含二进制代码和数据,区别就是这些文件已经经过链接,因此这些文件是可以直接执行的。

共享目标文件:这是一种特殊类型的可重定位的目标文件,可以在需要它的程序运行过程或者加载时,动态的加载到内存中运行。这种文件的后缀通常为“.so”, 共享目标文件又称为“动态库”文件或者“共享库”文件。

 

符号解析

符号解析是链接的主要任务之一。只有在正确的解析了符号之后才能更改引用符号的位置,从而完成重定位,生成一个可以被机器直接加载执行的的可执行目标文件。每个可重定位目标文件都有一个符号表。在这个符号表中存储符号。这些符号分为3类:

本模块中引用其他模块所定义的全局符号。

本模块中定义的全局符号。

本模块中定义和引用的局部符号。

 

重定位

在符号解析结束后,每个符号的定义位置及大小都是已知的了。重定位操作只需要将这些符号链接起来。在该步骤中,链接器需要将所有参与链接的目标文件合并,并且为每一个符号分配存储内容的运行时地址。

重定位分为2个步骤进行:

重定位段:该步将所有目标文件中同类型的段合并,生成一个大段。比如,将所有参与链接的目标文件的数据段合并,生成一个大的数据段。合并之后,程序中的指令和变量就拥有一个统一并且唯一的运行时地址了。

重定位符号引用:由于目标文件中相同的段已经合并,因此程序中对符号的引用位置就都作废了。这时链接器需要修改这些引用符号的地址,使其指向正确的运行时地址。

程序库

所谓“程序库”就是包含了一些通用函数的数据和二进制可执行机器码的文件。这些文件是目标文件的一种,其不能单独执行。但是若与其他的可执行程序结合起来就可以执行了。

从链接方式上区别,程序库可分为静态库和动态库(共享库)两种:

静态库:是在可执行程序运行前就已经加入到执行代码中,成为执行程序的一部分来执行的。

动态库:是在执行程序启动时加载到执行程序中,可以被多个执行程序共享使用。

静态库

静态库是一些目标代码的集合。linux下静态目标文件一般以.a作为目标文件的后缀。在Linux环境下使用ar命令来创建一个静态库。静态库的优点就是在生成时已经编译成可重定位的目标文件,节省了编译时间,并且在编译时把代码复制到可执行代码段中,这样可执行程序就可以单独直接运行,但是缺点也是显而易见的,就是可执行文件可能会变得很臃肿。

静态库的创建

本文以四则运算来创建一个静态库,该静态库中包含四个函数:加、减、乘、除。

// static_lib.c
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}

生成一个可重定位的目标文件。

# gcc -c static_lib.c

在Linux下使用 ar 命令创建一个静态库,或者将目标文件加入到一个已经存在的静态库中。其使用方法如下:

ar rcs 静态库名 目标文件1 目标文件2 ... 目标文件n

该命令表示将目标文件1~n加入到指定的静态库中。若该静态库不存在,则创建静态库文件,并将库文件的扩展名命名为.a, 其中rcs这三个参数分别表示:把列表中的目标文件加入到静态库中(r);若指定的静态库不存在,则创建该库文件(c);更新静态库文件的索引,使之包含新加入的目标文件的内容(s)。

使用生成的 static_lib.o 目标文件创建一个静态库 static_lib.a

# ar rcs static_lib.a static_lib.o

查看生成的静态库文件

# ls
static_lib.a static_lib.c static_lib.o

 

静态库的使用

创建的静态库需要链接到应用程序中才能使用,为了方便引用,我们创建一个头文件,使用时把该头文件包含到应用程序中。

//static_lib.h
extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);

编写应用程序

//test.c
#include <stdio.h>
#include "static_lib.h"
int mAIn()
{
int a = 8, b = 4;
printf("the add : %dn", add(a, b));
printf("the sub : %dn", sub(a, b));
printf("the mul : %dn", mul(a, b));
printf("the div : %dn", div(a, b));
}

编译

# gcc test.c -o test -L. static_lib.a
或者
#gcc test.c -o test ./static_lib.a

运行

# ./test
the add :12
the sub :4
the mul :32
the div :2

 

动态库

动态库又称为共享库或者动态链接库。在 Linux 环境下为 so 文件。动态库是在程序运行时加载的。当一个应用程序装载了一个动态库后,其他应用程序仍可以装载同一个动态库。这个被多个进程同时使用的动态库在内存中只有一个副本,因此动态库易于程序模块的更新,更新库并不影响应用程序使用旧的、非向后兼容的版本。

创建动态库

我们依然使用以四则运算来创建一个动态库,该动态库中包含四个函数:加、减、乘、除。

// share_lib.c
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}

Linux 下使用 gcc 创建一个动态库。由于动态库可以被多个进程共享加载,所以需要生成位置无关的目标文件。因此需要使用 gcc 编译器的 -fPIC 选项,该选项用于生成位置无关的代码。除了使用 -fPIC 选项,还需要使用 -shared 选项,该选项将位置无关的代码制作为动态库。

创建动态库的方法如下

# gcc -shared -fPIC -o share_lib.so share_lib.c
# ls
share_lib.so share_lib.c

动态库的使用

为了使应用程序可以正确的引用该库中的全局符号,需要制作一个包含该动态库文件中的全局符号声明的头文件。

//share_lib.h
extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);

编写一个应用程序使用动态库

//main.c
#include <stdio.h>
#include "share_lib.h"
int main()
{
int a = 8, b = 4;
printf("the add : %dn", add(a, b));
printf("the sub : %dn", sub(a, b));
printf("the mul : %dn", mul(a, b));
printf("the div : %dn", div(a, b));
}

运行

# gcc main.c ./share_lib.so -o main
# ./main
the add :12
the sub :4
the mul :32
the div :2



Tags:   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
新增融券再启动暂停键,有头部券商融券池全部收回!融券余额已较年初下降近四成
4月11日,A股市场触底反弹。其中,有一则消息是触发市场反弹的重要原因:据称,多家券商暂停新增融券通券源,拟阶段性临停融券通券源每日新增投放。《每日经济新闻》向某华东头部券商...【详细内容】
2024-04-11  Search:   点击:(1)  评论:(0)  加入收藏
16个Redis常见使用场景总结
来源:blog.csdn.net/qq_39938758/article/details/105577370目录 缓存 数据共享分布式 分布式锁 全局ID 计数器 限流 位统计 购物车 用户消息时间线timeline 消息...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
一篇文章教会你使用Python中三种简单的函数
所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。一、函数简介所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。二、函数定义...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
聊聊Rust里面的数据类型
嘿,朋友们!今天我们来聊聊Rust里面的数据类型。你知道吗?Rust的数据类型可是很重要的哦,它们帮助我们定义变量和函数可以处理什么样的数据。基本数据类型首先,让我们来看看Rust提...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
一篇文章带你了解Python的分布式进程接口
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。一、前言在Thread和Process中,应当优...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
网络安全行业的春天何时来?
2023年下半年开始,网络安全从业人员都感受到了网安行业的寒冬,但是其实前奏并不是此刻,只是涉及到大量裁员关乎自身而人人感同身受。从近五年各个网络安全上市公司财报可以发现...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
Linux获取Redis 性能指标方法
一、监控指标&Oslash; 性能指标:Performance&Oslash; 内存指标: Memory&Oslash; 基本活动指标:Basic activity&Oslash; 持久性指标: Persistence&Oslash; 错误指标:Error二、监...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
Redis与缓存一致性问题
缓存一致性问题是在使用缓存系统,如Redis时经常遇到的问题。当数据在原始数据源(如数据库)中发生变化时,如何确保缓存中的数据与数据源保持一致,是开发者需要关注的关键问题。一...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
10余所高校公布强基计划,今年有哪些变化?
今天,中国人民大学、中国农业大学、复旦大学、武汉大学、山东大学、吉林大学、重庆大学、大连理工大学发布了2024年强基计划招生简章。目前,已有10余所高校发布了招生简章。它...【详细内容】
2024-04-11  Search:   点击:(2)  评论:(0)  加入收藏
▌简易百科推荐
微软 Win11 Linux 子系统(WSL)发布 2.2.2 版本
IT之家 4 月 8 日消息,微软近日更新 Windows Subsystem for Linux(WSL),最新 2.2.2 版本中带来了诸多改进,重点更新了 nft 规则,可以让 IPv6 流量通过 Linux 容器。图源: dev.to,AI...【详细内容】
2024-04-08    IT之家  Tags:Linux   点击:(6)  评论:(0)  加入收藏
从原理到实践:深入探索Linux安全机制
Linux 是一种开源的类Unix操作系统内核,由Linus Torvalds在1991年首次发布,其后又衍生出许多不同的发行版(如Ubuntu、Debian、CentOS等)。前言本文将从用户和权限管理、文件系统...【详细内容】
2024-03-27  凡夫编程  微信公众号  Tags:Linux安全   点击:(16)  评论:(0)  加入收藏
在Linux系统中,如何处理内存管理和优化的问题?
本文对 Linux 内存管理和优化的一些高级技巧的详细介绍,通过高级的内存管理技巧,可以帮助系统管理员和开发人员更好地优化 Linux 系统的内存使用情况,提高系统性能和稳定性。在...【详细内容】
2024-03-26  编程技术汇  微信公众号  Tags:Linux   点击:(10)  评论:(0)  加入收藏
Linux 6.9-rc1 内核发布:AMD P-State 首选核心、BH 工作队列
IT之家 3 月 25 日消息,Linus Torvalds 宣布,Linux 6.9 内核的首个 RC(候选发布)版 Linux 6.9-rc1 发布。▲ Linux 6.9-rc1Linus 表示,Linux 内核 6.9 看起来是一个“相当正常”...【详细内容】
2024-03-25    IT之家  Tags:Linux   点击:(11)  评论:(0)  加入收藏
轻松实现Centos系统的软件包安装管理:yum指令实战详解
yum 是一种用于在 CentOS、Red Hat Enterprise Linux (RHEL) 等基于 RPM 的 Linux 发行版上安装、更新和管理软件包的命令行工具。它可以自动解决软件包依赖关系,自动下载并...【详细内容】
2024-02-27  凡夫贬夫  微信公众号  Tags:Centos   点击:(54)  评论:(0)  加入收藏
Win + Ubuntu 缝合怪:第三方开发者推出“Wubuntu”Linux 发行版
IT之家 2 月 26 日消息,一位第三方开发者推出了一款名为“Wubuntu”的缝合怪 Linux 发行版,系统本身基于 Ubuntu,但界面为微软 Windows 11 风格,甚至存在微软 Windows 徽标。据...【详细内容】
2024-02-27    IT之家  Tags:Ubuntu   点击:(49)  评论:(0)  加入收藏
Linux中磁盘和文件系统工作原理解析
在Linux系统中,一切皆文件的概念意味着所有的资源,包括普通文件、目录以及设备文件等,都以文件的形式存在。这种统一的文件系统管理方式使得Linux系统具有高度的灵活性和可扩展...【详细内容】
2024-02-20  王建立    Tags:Linux   点击:(51)  评论:(0)  加入收藏
Linux子系统概览
inux操作系统是一个模块化的系统,由多个子系统组成。这些子系统协同工作,使Linux能够执行各种任务。了解Linux的子系统有助于更好地理解整个操作系统的运作机制。以下是Linux...【详细内容】
2024-02-01    简易百科  Tags:Linux   点击:(77)  评论:(0)  加入收藏
Linux内核:系统之魂与交互之源
内核,作为任何基于Linux的操作系统的心脏,扮演着至关重要的角色。它不仅是计算机系统软件与硬件之间的桥梁,更是确保系统稳定、高效运行的关键。内核提供了一系列核心功能,为上...【详细内容】
2024-02-01  松鼠宝贝    Tags:Linux内核   点击:(68)  评论:(0)  加入收藏
如何确保Linux进程稳定与持久
在Linux系统中,进程的稳定性与持久性对于维持系统的持续运行至关重要。然而,由于各种原因,进程可能会面临崩溃或系统重启的情况。为了确保关键进程能够持续运行,我们必须采取一...【详细内容】
2024-01-19  松鼠宝贝    Tags:Linux进程   点击:(85)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条