Linux 动态库链接详解

linux c多进程引用动态库全局变量是否影响实验 1、描述:动态库中声明的全局变量,有两个进程都会调用并且赋值,需要确定两者调用是否影响。2、代码举例test_liba.h:int num;int funa(char *procname);===========================test_liba.c:#include "test_liba.h"int funa(char *procname){    printf("procnam... 阅读详情

转自

https://www.cnblogs.com/MaAce/p/7999795.html

静态库的缺点:

  1. 库函数被包含在每一个运行的进程中,会造成主存的浪费。
  2. 目标文件的size过大
  3. 每次更新一个模块都需要重新编译,更新困难,使用不方便。

动态库: 是一个目标文件,包含代码和数据,它可以在程序运行时动态的加载并链接。修改动态库不需要重新编译目标文件,只需要更新动态库即可。动态库还可以同时被多个进程使用。在linux下生成动态库 gcc -c a.c  -fPIC -o a.o     gcc -shared -fPIC a.o -o a.so.     这里的PIC含义就是生成位置无关代码,动态库允许动态装入修改,这就必须要保证动态库的代码被装入时,可执行程序不依赖与动态库被装入的位置,即使动态库的长度发生变化也不会影响调用它的程序。

动态链接器:

在加载可执行文件时,加载器发现在可执行文件的程序头表中有.interp段,其中包含了动态连接器路径ld-linux.so . 加载器加载动态链接器,动态链接器完成相应的重定位工作后,再将控制权交给可执行文件。

程序头:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [正在请求程序解释器:/lib64/ld-linux-x86-64.so.2]

位置无关代码PIC:

其中动态库用到的一个核心概念就是与代码无关PIC。共享库代码位置可以是不确定的,即使代码长度发生变化也不影响调用它的程序,动态链接器是不会把可执行文件的代码段数据段与动态链接库合并的。那么这里牵涉到模块内与模块间的引用和跳转问题。

模块内的跳转和引用:

//b.c
static int temp = 12344;
extern int a;
void add(int c)
{
    a += c;
    temp += c;
}

//a.c
int a = 1000;
void add(int c);
int main()
{
    int c = 123;
    add(c);
    return 0;

}

我们将b.c编译为动态库,这里的temp就是模块内的引用,我们将动态库反编译可以看到

00000000000006a8 <add>:
 6a8:   55                      push   %rbp
 6a9:   48 89 e5                mov    %rsp,%rbp
 6ac:   89 7d fc                mov    %edi,-0x4(%rbp)
 6af:   48 8b 05 2a 09 20 00    mov    0x20092a(%rip),%rax        # 200fe0 <    _DYNAMIC+0x1d0>
 6b6:   8b 10                   mov    (%rax),%edx
 6b8:   8b 45 fc                mov    -0x4(%rbp),%eax
 6bb:   01 c2                   add    %eax,%edx
 6bd:   48 8b 05 1c 09 20 00    mov    0x20091c(%rip),%rax        # 200fe0 <    _DYNAMIC+0x1d0>
 6c4:   89 10                   mov    %edx,(%rax)
 6c6:   8b 15 5c 09 20 00       mov    0x20095c(%rip),%edx        # 201028 <    temp>
 6cc:   8b 45 fc                mov    -0x4(%rbp),%eax
 6cf:   01 d0                   add    %edx,%eax
 6d1:   89 05 51 09 20 00       mov    %eax,0x200951(%rip)        # 201028 <    temp>
0000000000201028 <temp>:             #数据段temp
  201028:   38 30                   cmp    %dh,(%rax)

这里的mov 0x20095c(%rip),%edx  取rip中下一条指令地址+0x20095c 的数据放到edx寄存器中,地址为0x201028 正是temp的地址。模块内的函数跳转与此类似。

模块间的跳转和引用:

首先看一下全局变量的引用,看上例中b.so的反编译 这里引用了一个全局变量a 它的定义在另一个模块a.o 中

00000000000006a8 <add>:
 6a8:   55                      push   %rbp
 6a9:   48 89 e5                mov    %rsp,%rbp
 6ac:   89 7d fc                mov    %edi,-0x4(%rbp)
 6af:   48 8b 05 2a 09 20 00    mov    0x20092a(%rip),%rax        # 200fe0 <    _DYNAMIC+0x1d0>
 6b6:   8b 10                   mov    (%rax),%edx
 6b8:   8b 45 fc                mov    -0x4(%rbp),%eax
 6bb:   01 c2                   add    %eax,%edx
 6bd:   48 8b 05 1c 09 20 00    mov    0x20091c(%rip),%rax        # 200fe0 <    _DYNAMIC+0x1d0>
Disassembly of section .got:

0000000000200fd0 <.got>:
    ...

Disassembly of section .got.plt:

0000000000201000 <_GLOBAL_OFFSET_TABLE_>:
  201000:   10 0e                   adc    %cl,(%rsi)
  201002:   20 00                   and    %al,(%rax)

这里的mov 取地址是一个got数组的某个地址。GOT 全局偏移表,在data段的开始处的一个指针数组,每一个指针可以指向一个全局变量, GOT与引用数据的指令之间的相对距离固定,编译器为GOT每一项生成一个重定位项,加载时 动态链接器对GOT中的各项进行重定位,填入引用的地址。(32位 占4个字节  64位 8个字节)

每一个引用全局数据的目标模块都有一张自己的GOT,那么就需要一个额外的寄存器来保持GOT表目的地址。至于模块间的函数调用和跳转也可以使用此模块,但是这种情况下过程调用都要求三条额外的指令,Linux这里就使用了叫做延迟绑定的技术,将过程调用的绑定推迟到第一次调用该过程。这种技术是通过俩个数据结构之间的交互来实现,即GOT 和PLT 全局偏移表和过程链接表, 如果一个目标模块调用定义在共享库中的任何函数,那么它就有自己的GOT和PLT,GOT是data节的一部分,PLT是text节的一部分 —— 《深入理解计算机系统》

上图为 32 位linux。 从GOT[3]开始才是函数调用地址。我们将a.c b.so编译链接为可执行文件a, 反汇编a 观察函数add的调用(无关代码已省略)。(64位机器)

Disassembly of section .plt:
<add@plt-0x10>:
  400580:    ff 35 82 0a 20 00        pushq  0x200a82(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
  400586:    ff 25 84 0a 20 00        jmpq   *0x200a84(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
  40058c:    0f 1f 40 00              nopl   0x0(%rax)
<add@plt>:
  400590:    ff 25 82 0a 20 00        jmpq   *0x200a82(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> // ////++++++++++++++++++++++
  400596:    68 00 00 00 00           pushq  $0x0
  40059b:    e9 e0 ff ff ff           jmpq   400580 <_init+0x20>

00000000004005a0 <__libc_start_main@plt>:
  4005a0:    ff 25 7a 0a 20 00        jmpq   *0x200a7a(%rip)        # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
  4005a6:    68 01 00 00 00           pushq  $0x1
  4005ab:    e9 d0 ff ff ff           jmpq   400580 <_init+0x20>


00000000004006b0 <main>:
  4006b0:    55                       push   %rbp
  4006b1:    48 89 e5                 mov    %rsp,%rbp
  4006b4:    48 83 ec 10              sub    $0x10,%rsp
  4006b8:    c7 45 fc 7b 00 00 00     movl   $0x7b,-0x4(%rbp)
  4006bf:    8b 45 fc                 mov    -0x4(%rbp),%eax                
  4006c2:    89 c7                    mov    %eax,%edi                                      
  4006c4:    e8 c7 fe ff ff           callq  400590 <add@plt>           //call add--------------------------------
  4006c9:    b8 00 00 00 00           mov    $0x0,%eax
  4006ce:    c9                       leaveq 
  4006cf:    c3                       retq   


Disassembly of section .got:

0000000000600ff8 <.got>:
    ...

Disassembly of section .got.plt:
#data段  无效反编译代码
<_GLOBAL_OFFSET_TABLE_>:
  601000:   GOT[0]   GOT    64位下每个条目8个字节   32位是4个字节
  601008:   GOT[1] 链接器标示信息
 GOT[2]  动态连接器入口地址
  601017:    00 96 05 40 00 00        add    %dl,0x4005(%rsi)
  60101d:    00 00                    add    %al,(%rax)
  60101f:    00 a6 05 40 00 00        add    %ah,0x4005(%rsi)
  601025:    00 00                    add    %al,(%rax)
  601027:    00 b6 05 40 00 00        add    %dh,0x4005(%rsi)
  60102d:    00 00                    add    %al,(%rax)
    ...

我们可以看到main函数中跳转call add 跳转到了地址0x400590 处,执行 jmpq *0x200a82(%rip) 指令 跳转到 0x601018的地址 ,还是跳到GOT数组中的add位置。这个位置其实就是 jmpq *0x200a82(%rip)的下一条指令地址400596: 68 0000 00 00 pushq $0x0。我们可以使用gdb看一下。

(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004006b0 <+0>:   push   %rbp
   0x00000000004006b1 <+1>:   mov    %rsp,%rbp
   0x00000000004006b4 <+4>:   sub    $0x10,%rsp
=> 0x00000000004006b8 <+8>:    movl   $0x7b,-0x4(%rbp)
   0x00000000004006bf <+15>:  mov    -0x4(%rbp),%eax
   0x00000000004006c2 <+18>:  mov    %eax,%edi
   0x00000000004006c4 <+20>:  callq  0x400590 <add@plt>
   0x00000000004006c9 <+25>:  mov    $0x0,%eax
   0x00000000004006ce <+30>:  leaveq
   0x00000000004006cf <+31>:  retq  
End of assembler dump.
(gdb) disassemble 0x400590
Dump of assembler code for function add@plt:
   0x0000000000400590 <+0>:   jmpq   *0x200a82(%rip)        # 0x601018 <add@got.plt> 这个地址就是GOT数组中add对应的那条
   0x0000000000400596 <+6>:   pushq  $0x0
   0x000000000040059b <+11>:  jmpq   0x400580
End of assembler dump.
(gdb) x 0x601018
0x601018 <add@got.plt>:   0x00400596

pushq $0x0 这条指令将add符号的ID压入栈,然后 jmpq  0x400580 它将会跳转到PLT[0]接下来的指令就是:

0000000000400580 <add@plt-0x10>:
  400580:    ff 35 82 0a 20 00        pushq  0x200a82(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>   链接器标示信息入栈  前面还有个ID
  400586:    ff 25 84 0a 20 00        jmpq   *0x200a84(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>  跳转到链接器入口地址
  40058c:    0f 1f 40 00              nopl   0x0(%rax)

跳转到动态连接器之后,链接器根据这两个栈中的信息(其实就是重定位描述符地址和索引值)得到 add的实际地址, 在将地址放入GOT[3]中 通过gdb详细看一下。

(gdb) n
       add(c);  运行  add之前
(gdb) x /32x 0x601010
0x601010:    0xf7df0210    0x00007fff    0x00400596    0x00000000  
这时GOT[3]add地址还不是add的实际地址 而是0000000000400590<add@plt>: jmp的目的地址0x00400596
0x601020 <__libc_start_main@got.plt>:    0xf7839a20    0x00007fff    0x004005b6    0x00000000
0x601030:    0x00000000    0x000003e8    0x00000000    0x00000000
0x601040:    0x00000000    0x00000000    0x00000000    0x00000000
0x601050:    0x00000000    0x00000000    0x00000000    0x00000000
0x601060:    0x00000000    0x00000000    0x00000000    0x00000000
0x601070:    0x00000000    0x00000000    0x00000000    0x00000000
0x601080:    0x00000000    0x00000000    0x00000000    0x00000000
(gdb) print add
$2 = {<text variable, no debug info>} 0x7ffff7bd96a8 <add>   add函数的地址
(gdb) n
       return 0;
(gdb) x /32x 0x601010
0x601010:    0xf7df0210    0x00007fff    0xf7bd96a8    0x00007fff   
进入add GOT[3]中地址变为了 add的实际地址 再之后的
<add@plt>: jmpq *0x200a82(%rip) 就会直接跳到add的地址 开始执行指令。


0x601020 <__libc_start_main@got.plt>:    0xf7839a20    0x00007fff    0x004005b6    0x00000000
0x601030:    0x00000000    0x00000463    0x00000000    0x00000000
0x601040:    0x00000000    0x00000000    0x00000000    0x00000000
0x601050:    0x00000000    0x00000000    0x00000000    0x00000000
0x601060:    0x00000000    0x00000000    0x00000000    0x00000000
0x601070:    0x00000000    0x00000000    0x00000000    0x00000000
0x601080:    0x00000000    0x00000000    0x00000000    0x00000000

这里可以看到被引用的函数调用之前 GOT中的地址并没有被值为函数的实际地址。之后实际地址就被装入,跳转到相应地址开始执行,之后就可以直接跳转运行了,只需要一个跳转指令即可。

搞懂Linux动态库依赖:为什么你的dlopen加载会失败?从链接器优化到rpath详解 本文深入解析Linux动态库依赖问题,特别是dlopen加载失败的原因及解决方案。从链接器优化机制到rpath设置,详细介绍了如何解决常见的符号未定义错误,并提供了多种实战技巧和最佳实践,帮助开发者有效管理动态库依赖关系。 阅读详情

相关推荐

OASIS协议标准文档的解读_第一部分

OASIS标准协议的文档的解读。完整原协议的中文翻译和解读。

洋葱的专栏 4903

多进程引用动态链接库中的全局变量问题

多进程引用动态链接库中的全局变量问题 现象描述: 前提:存在一个动态库libvlan.so,存在一个应用console。 做法:在console中调用libvlan.so中的两个APIs,分别是设置和获取动态库中一个全局变量的值。 结果:在console中的操作没有问题,设置和获取都正常;但在动态库中打印该全局变量,其值并没有改变。 结论:动态库中的全局变量,在被其他进程使用...

团长的专栏 7782

Mac新手必看:用Homebrew安装wget的保姆级教程,附常见报错一键修复

本文为Mac新手提供使用Homebrew安装wget的详细教程,涵盖从Homebrew安装到wget基础使用的全流程,并附常见报错一键修复方案。通过本指南,用户可轻松掌握命令行下载工具wget的安装与使用技巧,解决Mac环境下资源下载的各种问题。

weixin_30635053的博客 366

Linux 链接详解----动态链接库

静态库的缺点: 库函数被包含在每一个运行的进程中,会造成主存的浪费。 目标文件的size过大 每次更新一个模块都需要重新编译,更新困难,使用不方便。 动态库: 是一个目标文件,包含代码和数据,它可以在程序运行时动态的加载并链接。修改动态库不需要重新编译目标文件,只需要更新动态库即可。动态库还可以同时被多个进程使用。在linux下生成动态库 gcc -c a.c -fPIC -o ...

weixin_34401479的博客 368

SAR ADC设计——SAR Logic原理

SAR ADC设计——SAR Logic原理 参考:集成电路设计实践 SAR ADC 清华大学 李福乐 文章目录SAR ADC设计——SAR Logic原理一. Overview二. TSPC(True Single Phase Clock)三. SC_Gen(Sequential Control Generator)四. LATCH_Dynamic五. 时序控制逻辑总结六. SW产生七. DO产生八. GT产生九. SAR Logic模块总结 一. Overview 输入:CKC,CompB,SAMPL

夏风喃喃的博客 1万+

基因组注释(Annotation)

Annotation

hgz2020的博客 6490

多进程访问动态库全局变量问题

1、如果你做的动态库里面有全局变量,而且你想让不同的jinc

ostar_liang的专栏 7264

固定资产报废的损失鉴定怎么做?

在社会生产的日常中,企业经常会遇到固定资产报废的损失鉴定,那么怎么去做鉴定?哪些情况下能申请固定资产报废损失鉴定呢? 今天,华碧鉴定就和大家说一说固定资产报废损失鉴定那些事儿。 符合下列条件之一的固定资产可申请报废: 1、使用年限过长,功能丧失,完全失去使用价值,或不能使用并无修复价值的; 2、产品技术落后,质量差,耗能高,效率低,已属淘汰且不适于继续使用,或技术指标已达不到使用要求的; 3、严重损坏,无法修复的或虽能修复,但累计修理费已接近或超过市场价值的; 4、主要附件损坏,无.

weixin_50362670的博客 2116

Linux共享库(动态库)与进程之间共享全局变量可行性分析

在主程序中可以使用动态链接库中的全局变量是正确的,不可否认的,但这需要在程序编译链接时就要把动态库加上,并在需要使用的程序中使用extern声明变量,这其实没有达到动态库的本质目的(使用时再调用);这其实不算是一个大问题,如果只在一个进程中使用也不会有问题,这里主要讨论在多进程中使用动态库全局变量的问题。 如果想在进程间依靠动态库来共享全局变量恐怕是不太可能的事情,因为不同进程访问动态库时,是写

许振坪的专栏 3268

漏洞挖掘之工具配置

本文主要讲解burp工具的插件安装。

qq_64775230的博客 3273

目标检测旋转增强源码带方向

解法1: import cv2 import math import numpy as np import os def get_degree(p1,p0): aaa = math.degrees(math.atan2((p1[1] - p0[1]), (p1[0] - p0[0]))) if aaa < 0: aaa = 360 + aaa aaa = (aaa + 90) if aaa > 360: aa...

jacke121的专栏 2084

动态库的链接详解-linux

链接动态库 为什么需要链接? 作为编译的最后一公里和运行的刚需。 linux从程序(program或对象)变成进程(process或进程)简单的说分三步: 1、fork进程,在内核创建进程相关内核项,加载进程可执行文件; 2、查找依赖的so,一一加载映射虚拟地址 3、初始化程序变量。 来看一看链接的细节: 此文环境 [root@VM_0_9_centos dynamic_...

Gdl.痕迹 的博客 501

数字滤波器应用介绍

线性滤波器FIR ,会引起恒定延迟,通过补零的方式补偿非线性滤波器IIR,会引起频率相关的延迟,通过零相位延迟filtfilt补偿从信号中去除不需要的频谱时,通过滤波和补偿实现。如果需要去除的频率与采样率相差甚远,比如4kHz 与100Hz, 可通过 低通滤波->补偿->降采样–> 滤波 补偿 -->上采样还原的方法。*降采样前一定要先低通滤波为了防止混叠。

weixin_39107270的博客 274

Linux C/C++ 编译链接动态库详解

在 Linux C 编译时链接动态库,需要使用 -l 参数指定要链接的动态库名称,同时需要指定动态库的搜索路径。这样就会链接 libtest1.so 和 libtest2.so 两个动态库。这样就会在 /opt/mylib 目录下搜索 libtest.so 动态库。其中,-L 参数指定动态库的搜索路径,-l 参数指定要链接的动态库名称。

Michael 2546

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【Linux】详解动态库链接和加载&&对可执行程序底层的理解

【Linux】详解动态库链接和加载&&对可执行程序底层的理解

m0_74265792的博客 2440

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Linux平台下GCC/G++编译与链接静态库和动态库详解

本文详细讲解了Linux平台下使用GCC/G++编译和链接静态库(.a)与动态库(.so)的方法。主要内容包括:库的基本概念和原理对比;静态库的生成步骤、链接方式及命名规范;动态库的创建过程、位置无关代码编译和运行时加载机制;关键编译选项详解;完整的库创建到程序运行的示例;动静态库的优缺点比较;以及常见问题的解决方案。文章通过实例代码和命令演示,帮助开发者掌握模块化编程的核心技术,实现代码的高效复用和管理。最后指出在实际项目中应根据需求合理选择库类型,并建议使用Makefile实现构建自动化。

songmake1987的博客 1085

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Linux动态库版本管理:从链接错误到Soname机制详解

动态链接库是Linux系统中实现代码共享和模块化开发的核心机制,它通过动态链接在程序运行时加载,有效减少了内存占用和磁盘空间。其工作原理基于ELF格式和动态链接器,通过符号解析和重定位实现函数调用。这一技术显著提升了软件的可维护性和部署效率,广泛应用于操作系统核心组件、桌面应用和服务端软件中。在实际开发中,开发者常会遇到动态库版本管理问题,例如链接错误和符号未定义等,这通常涉及Soname机制和ABI兼容性。本文通过分析libtest.so等常见库文件命名规范,深入解析了真实名称、共享库名和链接名三者的关系

weixin_30621711的博客 395

bazel 链接第三方动态库_Linux 动态库与静态库制作及使用详解

Linux 应用开发通常要考虑三个问题,即:1)在 Linux 应用程序开发过程中遇到过标准库链接在不同 Linux 版本下不兼容的问题; 2)在 Linux 静态库的制作过程中发现有别于 Windows 下静态库的制作方法;3)在 Linux 应用程序链接第三方库或者其他静态库的时候发现链接顺序的烦人问题。本文就这三个问题针对 Linux 下标准库链接和如何巧妙构建 achrive(*.a) 展...

weixin_39844549的博客 913

Linux动态库软链接详解:从现象到本质,嵌入式老鸟手把手教你避坑

本文详细解析了Linux动态库软链接的设计原理与实用场景。通过实际案例展示了一个MQTT动态库的完整链接结构,包括核心文件(libMqttServer.so.1.0.0)、三个层级软链接(不带版本号、主版本号、主次版本号)以及备份文件。重点阐述了这种设计的多重目的:短名链接(libMqttServer.so)供编译器使用,主版本号链接(libMqttServer.so.1)确保运行时ABI兼容,完整版本号文件便于版本管理。文章结合嵌入式开发实际经验,特别强调了这种机制对系统稳定性和升级维护的重要性,帮助开发

一无所知 424

吃透 Linux 静态库 / 动态库:ELF 文件、链接加载与进程地址空间详解

本文系统介绍了Linux中的静态库与动态库技术。深入分析了ELF文件格式,包括其组成结构(ELF头、程序头表、节头表等)和链接加载机制,重点解释了动态链接通过GOT表实现地址无关代码的原理。

Miun123的博客 1034

【Linux】详解动态库链接和加载&amp;&amp;对可执行程序底层的理解(2)

本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。库的实现方法一定是要跟程序运行起来所形成的进程产生关联的,动态库加载后,会被映射到该进程的地址空间中,准确来说,是先在页表中填写好对应虚拟地址和物理地址之间的映射关系,才被映射到进程地址空间中的共享区中。需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论。最全的Linux教程,Linux从入门到精通。

m0_62261166的博客 883

《从零入门Linux系统篇(三十五):文件篇·八——静态库与动态库详解:从制作链接到动态库加载》

本文作为 Linux 文件篇的第八部分,将深入学习程序开发中不可或缺的静态库与动态库。文章首先从库的本质入手,了解静态库与动态库的作用及命名规范;随后分别介绍两类库的制作、打包、发布与链接使用,并通过开发者与使用者的实际目录视角,理解库从生产到交付的完整过程。接着重点分析动态库运行时无法加载的问题,解释其背后的原因,并介绍通过系统标准路径、软链接、LD_LIBRARY_PATH 以及 ld.so.conf.d 配置解决的方法。最后结合 gcc 的默认行为,进一步理解动静态库混合链接时的优先级。

沫漓的博客 518

arm-linux-gcc生成静态库,gcc链接g++编译生成的静态库和动态库的makefile示例

使用c++开发程序或者库时,将库提供给其他人使用。然而使用者是使用c开发的程序,链接g++编译生成的库时,于链接gcc生成的库,有所不同。首先是静态库,以链接g++编译生成的libmylib.a为例子mylib依赖于pthread,rt,math库,链接时必须放在mylib之后。同时-Wl,--no-as-needed -ldl添加在末尾是必须的。arm和x86有些不同,就是arm的gcc不会自动...

weixin_42228776的博客 1902

linux文件的创建与扫描,LINUX创建和使用动态链接库

动态链接库文件在windows平台下往往以.dll为后缀,而在linux平台则一般以.so为后缀,so是shared object的缩写。采用gcc编译器,文件:adpcm.h, adpcm.c, main.c, 放在同一目录下(/home/hbapril)想做到windows和linux的文件共享,简单的设置共享不成功,其他方法好像要安装ftp或者其他专用软件的。main.c中调用adpcm中的...

weixin_36348900的博客 402

从libc.so.6软链接故障看Linux系统动态库管理的艺术

本文深入探讨了Linux系统中libc.so.6软链接故障的成因与解决方案,揭示了动态库管理的核心原理。通过分析glibc版本冲突导致的系统命令失效问题,提供了使用sln工具修复软链接的实战方法,并总结了动态库管理的最佳实践与架构设计哲学。

n4o5p6q7r的博客 211
上一篇: Linux内核模块间函数正确调用方法
下一篇: Linux段错误Segfault内核层面分析
SweeNeil
博客等级 码龄9年 251粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值