Linux 库开发入门:静态库与动态库的 2 种构建方式 + 5 个编译差异 + 3 个加载技巧,新手速看

文 章 目 录

  • [一、静 态 库 与 动 态 库 是 否 具 备 可 执 行(x)权 限](#一、静 态 库 与 动 态 库 是 否 具 备 可 执 行(x)权 限)
    • [1、静 态 库 无 "x" 权 限](#1、静 态 库 无 “x” 权 限)
    • [2、动 态 库 有 "x" 权 限](#2、动 态 库 有 “x” 权 限)
  • [二、动 静 态 库 在 代 码 编 译 链 接 中 的 作 用](#二、动 静 态 库 在 代 码 编 译 链 接 中 的 作 用)
    • [1、同 时 使 用 动 态 库 和 静 态 库](#1、同 时 使 用 动 态 库 和 静 态 库)
    • [2、静 态 库](#2、静 态 库)
      • [(1)编 译 前 删 除](#(1)编 译 前 删 除)
      • [(2)编 译 后 删 除](#(2)编 译 后 删 除)
      • [(3)总 结](#(3)总 结)
    • [3、动 态 库](#3、动 态 库)
      • [(1)删 除 动 态 库](#(1)删 除 动 态 库)
      • [(2)总 结](#(2)总 结)
  • [三、程 序 加 载](#三、程 序 加 载)
    • [1、动 态 库 的 加 载](#1、动 态 库 的 加 载)
    • [2、程 序 没 有 加 载 前 的 地 址](#2、程 序 没 有 加 载 前 的 地 址)
    • [3、程 序 加 载 后 的 地 址](#3、程 序 加 载 后 的 地 址)
    • [4、程 序 加 载 与 指 令 执 行 的 流 程](#4、程 序 加 载 与 指 令 执 行 的 流 程)
    • [5、动 态 库 的 地 址](#5、动 态 库 的 地 址)
  • [四、总 结](#四、总 结)

💻作 者 简 介:曾 与 你 一 样 迷 茫,现 以 经 验 助 你 入 门 Linux。

💡个 人 主 页:@笑口常开xpr 的 个 人 主 页

📚系 列 专 栏:Linux 探 索 之 旅:从 命 令 行 到 系 统 内 核

✨代 码 趣 语:静 态 库 像 打 包 食 材,全 拌 菜 里;动 态 库 像 现 用 调 料,没 它 没 味,得 有 权 限。

💪代 码 千 行,始 于 坚 持,每 日 敲 码,进 阶 编 程 之 路。

📦gitee 链 接:gitee

在 Linux 开 发 中,不 少 开 发 者 会 用 静 态 库(.a)和 动 态 库(.so),却 不 懂 底 层 细 节:为 什 么 静 态 库 不 用 x 权 限、动 态 库 必 须 有?为 啥 删 静 态 库 程 序 能 跑、删 动 态 库 就 崩 溃?程 序 从 磁 盘 到 内 存 运 行,地 址 转 换 和 库 加 载 是 怎 么 回 事?本 文 从 权 限 差 异 切 入,结 合 实 例 拆 解 静 动 态 库 的 编 译 依 赖,再 讲 透 程 序 加 载 的 虚 实 地 址 转 换、MMU 工 作 等 机 制,帮 你 理 清 这 些 模 糊 点,理 解 库 与 程 序 的 底 层 关 联。


一、静 态 库 与 动 态 库 是 否 具 备 可 执 行(x)权 限

1、静 态 库 无 "x" 权 限

静 态 库 的 核 心 作 用,是 提 供 编 译 后 的 二 进 制 代 码 片 段(而 非 源 代 码),供 编 译 链 接 阶 段 使 用。在 生 成 可 执 行 程 序 时,编 译 器 会 将 静 态 库 中 所 需 的 代 码 完 整 拷 贝 到 最 终 的 可 执 行 文 件 中 - - - 一 旦 编 译 完 成,可 执 行 程 序 就 已 包 含 静 态 库 的 全 部 必 要 功 能,后 续 运 行 时 不 再 依 赖 原 静 态 库,也 无 需 将 静 态 库 加 载 到 内 存。

由 于 静 态 库 仅 作 为 "代 码 片 段 的 容 器" 参 与 编 译,不 直 接 参 与 运 行 执 行,因 此 不 需 要 具 备 可 执 行(x)权 限。


2、动 态 库 有 "x" 权 限

动 态 库 采 用 "运 行 时 关 联" 的 机 制:编 译 阶 段 仅 会 在 可 执 行 程 序 中 记 录 "需 要 调 用 动 态 库" 的 关 联 信 息,不 会 将 动 态 库 的 代 码 拷 贝 到 可 执 行 文 件 中。当 可 执 行 程 序 启 动 运 行 时,系 统 需 要 将 对 应 的 动 态 库 加 载 到 内 存 中,可 执 行 程 序 会 在 运 行 过 程 中 动 态 从 内 存 中 的 动 态 库 调 用 所 需 功 能。

由 于 动 态 库 需 要 被 系 统 加 载 后 直 接 执 行 其 内 部 的 代 码 逻 辑,为 了 确 保 系 统 能 正 常 读 取 并 运 行 其 指 令,动 态 库 必 须 具 备 可 执 行(x)权 限。


二、动 静 态 库 在 代 码 编 译 链 接 中 的 作 用

1、同 时 使 用 动 态 库 和 静 态 库

javascript 复制代码
#include "mymath.h"
#include "mylog.h"
#include "myprint.h"

int main()
{
		//静态库
    int n = div(10,0);
    printf("10/0=%d,errno=%d\n",n,myerrno);
    //动态库
    Print();
    Log("hello log function");
    return 0;
}



2、静 态 库

(1)编 译 前 删 除

(2)编 译 后 删 除

(3)总 结

静 态 库 和 程 序 编 译 有 关,删 除 静 态 库 后 程 序 无 法 编 译,编 译 完 成 后,静 态 库 与 可 执 行 程 序 的 执 行 没 有 关 系。


3、动 态 库

(1)删 除 动 态 库

删 除 之 前

删 除 之 后

删 除 后,即 使 可 执 行 程 序 存 在,程 序 也 无 法 执 行,说 明 动 态 库 和 可 执 行 程 序 的 执 行 有 关。

(2)总 结

常 见 的 动 态 库 被 所 有 的 可 执 行 程 序(动 态 链 接 的),都 要 使 用 动 态 库,动 态 库 也 是 共 享 库。动 态 库 在 进 程 运 行 的 时 候,是 要 被 加 载 的。所 以,动 态 库 在 系 统 中 被 加 载 之 后,会 被 所 有 进 程 共 享。


三、程 序 加 载

1、动 态 库 的 加 载

动 态 库 也 是 文 件,建 立 映 射,从 此 往 后,执 行 的 任 何 代 码,都 是 在 进 程 地 址 空 间 中 运 行。

事 实 :系 统 中,一 定 会 存 在 多 个 动 态 库,操 作 系 统 会 管 理 起 来,即 先 描 述,再 组 织。系 统 中,所 有 库 的 加 载 情 况,操 作 系 统 非 常 清 楚。


2、程 序 没 有 加 载 前 的 地 址

  1. 程 序 编 译 好 之 后,形 成 可 执 行 程 序 后,内 部 有 地 址,代 码 在 编 译 时 就 会 形 成 地 址,不 需 要 函 数 名,可 执 行 程 序 在 没 有 被 加 载 到 内 存 时,已 经 被 分 成 了 很 多 段。

  2. 实 际 上,可 执 行 程 序 内 部 的 编 址 为 平 坦 模 式,磁 盘 上 的 可 执 行 程 序 内 部 编 址 顺 序 的 排 布 问 题 和 加 载 到 内 存 的 规 则 基 本 是 一 致 的。编 译 器 也 要 考 虑 操 作 系 统,编 译 器 需 要 考 虑 可 执 行 程 序 在 内 存 中 的 加 载。可 执 行 程 序 中 的 地 址 是 虚 拟 地 址,也 被 称 为 逻 辑 地 址,即 磁 盘 当 中 形 成 的 地 址。

  3. CPU 当 中 有 指 令 集,CPU 不 会 将 指 令 集 当 做 数 据 处 理,被 分 为 了 经 典 指 令 集 和 复 杂 指 令 集。

3、程 序 加 载 后 的 地 址

  1. 可 执 行 程 序 加 载 到 内 存 时 会 占 据 物 理 内 存。每 一 条 指 令 都 有 对 应 的 物 理 地 址 以 及 加 载 到 内 存 之 前 的 逻 辑 地 址。
  2. entry - - - 可 执 行 程 序 入 口 地 址,可 执 行 程 序 在 没 有 加 载 到 内 存 之 前,没 有 物 理 地 址。入 口 地 址 对 应 逻 辑 地 址。寄 存 器 当 中 有 EIP/PC 指 针。
  3. CPU 内 读 取 的 指 令,内 部 可 能 有 数 据,可 能 也 有 虚 拟 地 址。如 果 地 址 不 存 在,会 出 现 缺 页 中 断。整 个 操 作 系 统 的 CPU 识 别 的 都 是 虚 拟 地 址。

4、程 序 加 载 与 指 令 执 行 的 流 程

  1. 程 序 编 译 / 链 接 → 生 成
    编 译 器 将 源 代 码 编 译 为 "目 标 文 件",为 每 个 指 令、变 量 分 配 虚 拟 地 址。链 接 器 将 多 个 目 标 文 件 合 并 为 可 执 行 程 序,最 终 确 定 所 有 指 令 和 数 据 的 最 终 虚 拟 地 址。此 时 程 序 还 未 加 载 到 内 存,只 有 "虚 拟 地 址",没 有 任 何 物 理 地 址。
  2. 程 序 加 载 → 操 作 系 统 分 配 物 理 内 存 + 初 始 化 页 表

当 用 户 执 行 程 序 时,操 作 系 统 会 做 如 下 的 工 作:

(1)创 建 进 程 与 虚 拟 地 址 空 间 :为 该 程 序 创 建 独 立 进 程,分 配 一 套 完 整 的 虚 拟 地 址 空 间。

(2)分 配 物 理 内 存 页 :OS 从 空 闲 物 理 内 存 中,为 程 序 的 指 令、数 据 分 配 若 干 "物 理 页"。

(3)初 始 化 页 表:OS 在 内 存 中 为 该 进 程 创 建 "页 表",并 填 写 映 射 关 系。

先 有 虚 拟 地 址,再 分 配 物 理 地 址,最 后 初 始 化 页 表。页 表 的 本 质 是 记 录 虚 拟 地 址 到 物 理 地 址 的 映 射,没 有 虚 拟 地 址,页 表 就 没 有 映 射 的 对 象。

  1. CPU 执 行 指 令 → MMU 完 成 地 址 转 换
    当 程 序 开 始 运 行(CPU 执行第一条指令),流 程 如 下:
    (1)CPU 从 程 序 计 数 器(PC)中 读 取 第 一 条 指 令 的 虚 拟 地 址 。
    (2)CPU 将 该 虚 拟 地 址 发 送 给 内 置 的 MMU。
    (3)MMU 查 询 该 进 程 的 页 表,找 到 对 应 的 物 理 地 址。
    (4)MMU 将 物 理 地 址 发 送 给 内 存 控 制 器,内 存 控 制 器 从 该 物 理 地 址 中 读 取 指 令 数 据,返 回 给 CPU。
    (5)CPU 解 码 并 执 行 这 条 指 令,随 后 PC 自 动 指 向 下 一 条 指 令 的 虚 拟 地 址,重 复 上 述 步 骤。
  2. 按 需 加 载 与 地 址 映 射
    现 代 操 作 系 统 会 采 用 "按 需 分 页" 策 略:加 载 程 序 时,不 会 把 所 有 指 令/数 据 都 加 载 到 物 理 内 存,而 是 只 加 载 "当 前 需 要 执 行 的 页";当 CPU 访 问 的 虚 拟 地 址 对 应 的 物 理 页 未 加 载 到 内 存 时(触 发 "缺 页 异 常"),OS 会 临 时 从 磁 盘 加 载 该 页 到 物 理 内 存,并 更 新 页 表,之 后 再 恢 复 指 令 执 行。

5、动 态 库 的 地 址

静 态 库 没 有 加 载 是 因 为 静 态 库 会 被 直 接 拷 贝 到 可 执 行 程 序 里,静 态 库 在 可 程 序 中 的 位 置 是 确 定 的,与 位 置 有 关。


四、总 结

本 文 讲 清 了 静 动 态 库 与 程 序 加 载 的 核 心,这 些 知 识 能 帮 你 解 决 权 限、加 载 报 错,选 库 更 有 依 据(独 立 工 具 选 静 态 库,多 程 序 共 享 选 动 态 库)。后 续 可 探 索 库 版 本 管 理、动 态 库 延 迟 加 载,深 化 底 层 认 知,避 免 开 发 踩 坑。

相关推荐
SonOfWind03112 小时前
CentOS搭建本地源
linux·运维·centos
IT成长日记2 小时前
【Nginx开荒攻略】Nginx主配置文件结构与核心模块详解:从0到1掌握nginx.conf:
linux·运维·nginx·配置文件
Nimsolax2 小时前
Linux线程控制
linux
Light602 小时前
领码方案|Linux 下 PLT → PDF 转换服务超级完整版:异步、权限、进度(一气呵成)
linux·spring boot·pdf·gpcl6/ghostpcl·s3/oss·权限与审计·异步与进度
YuTaoShao3 小时前
【LeetCode 每日一题】36. 有效的数独
linux·算法·leetcode
智者知已应修善业3 小时前
【51单片机单按键控制2个LED循环闪烁】2022-12-7
c语言·经验分享·笔记·嵌入式硬件·51单片机
NiKo_W3 小时前
Linux 开发工具(1)
linux·运维·服务器
笑口常开xpr4 小时前
Linux动静态库开发基础:静态库与动态库的编译构建、链接使用及问题排查
linux·c语言·动态库·静态库
艾莉丝努力练剑4 小时前
【C++】类和对象(下):初始化列表、类型转换、Static、友元、内部类、匿名对象/有名对象、优化
linux·运维·c++·经验分享