首页 > 系统相关 >Linux环境下:程序的链接, 装载和库[动态链接]

Linux环境下:程序的链接, 装载和库[动态链接]

时间:2023-02-05 20:22:41浏览次数:62  
标签:动态 链接 装载 so Linux 动态链接库 main hello

静态链接库在程序编译阶段就完成了链接工作,完成链接后,依赖的库就都打入了可执行文件中,所以文件大小一般会比较大。
而动态库链接库是在程序运行时才被链接的,所以磁盘上只要保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。Linux环境下的动态链接对象都是以.so为扩展名的共享对象(Shared Object).

生成共享动态链接库

main_1.c

#include "hello.h"

int main()
{
    print_x(1);
    sleep(10000);
    return 0;
}

hello.c

#include <stdio.h>

void print_x(int x)
{
    printf("call hello.so x=%d\n",x);
}

生成共享动态链接库 gcc -fPIC -shared -o hello.so hello.c
将main函数链接此共享库 gcc -o main_1 main_1.c ./hello.so

PIC:Position Independnet Code -fPIC表示生成位置无关的代码
有些系统需要无论加载到什么位置都可以正常工作的位置无关代码。链接器需要提供额外的技巧来支持位置无关代码,与程序中无法做到位置无关的部分隔离开来。

通过/proc 文件系统可以查看动态链接的程序在运行时会加载的额外的库有哪些
image.png
除了我们程序本身的main_1的段,还依赖了

  • hello.so这个是我们创建的动态链接库
  • libc.so.6这个是hello文件中所依赖的
  • ld-linux-x86-64.so.2这个是linux上的动态链接器。 使用动态链接库的时候,操作系统在运行程序之间,会先将控制权交给动态链接器,即/lib64/ld-linux-x86-64.so.2,它完成了动态链接的工作之后再把控制权交给应用程序。所以会在进程空间中看到这个

通过动态链接生成的main_1可执行文件中存储了这个信息,通过 readelf -s main_1查看 .interp section的内容
image.png

.interp
This section holds the pathname of a program interpreter. If the file has a loadable segment that includes the section, the section's attributes
will include the SHF_ALLOC bit. Otherwise, that bit will be off. This section is of type SHT_PROGBITS.

但是这样的依赖动态链接库,对最终运行时的动态链接库的位置有要求,将hello.so移动位置后就无法找到了。
image.png

可执行文件的运行时入口

真正可执行文件的运行时入口并不是main函数,而是glibc的运行时库,在执行main函数之前需要做一些初始化的工作。大部分Linux程序的入口地址应该都是 glibc 中的_start 函数
image.png
objdump -d ../PartIV/sta_vs_dyn/dyn_loop
image.png
这个对应glibc中的一段入口函数。

基本上到这里就理解了程序的编译,链接和装载的过程。文章只是跟随视频学习过程的一点记录,有些阅读linux内核的源码没有完全跟进去,感兴趣的可以看看原作者的分享视频

https://www.bilibili.com/video/BV1hv411s7ew/

标签:动态,链接,装载,so,Linux,动态链接库,main,hello
From: https://www.cnblogs.com/Aitozi/p/17093885.html

相关文章

  • 忘记Linux系统密码,简单一招搞定
    这里以centos7为例,蜜蜂最近老是收到朋友说电脑密码忘了怎么办。今天蜜蜂就来演示一遍Linux密码忘了的解决方法,意在帮助常忘记自己密码的朋友们。其实方法有很多,在这里蜜蜂就......
  • Linux安装配置RabbitMq
    Linux安装配置RabbitMq安装Erlanghttps://www.erlang.org/downloads安装依赖包yuminstallgccglibc-develmakencurses-developenssl-develautoconfyuminstall......
  • Linux部署-Net并配置进程守护
    Linux部署-Net并配置进程守护注册Microsoft签名密钥并添加Microsoft产品提要sudorpm--importhttps://packages.microsoft.com/keys/microsoft.ascsudosh-c'e......
  • Linux硬盘读写性能测试
    使用方式ddif=path/to/input_fileof=/path/to/output_filebs=block_sizecount=number_of_blocks示例测试硬盘写能力timeddif=/dev/zeroof=/testw.dbfbs=4kcount=10......
  • Linux安装配置RabbitMq
    Linux安装配置RabbitMq安装Erlanghttps://www.erlang.org/downloads安装依赖包yuminstallgccglibc-develmakencurses-developenssl-develautoconfyuminstall......
  • Linux部署-Net并配置进程守护
    Linux部署-Net并配置进程守护注册Microsoft签名密钥并添加Microsoft产品提要sudorpm--importhttps://packages.microsoft.com/keys/microsoft.ascsudosh-c'e......
  • Linux安装配置RabbitMq
    Linux安装配置RabbitMq安装Erlanghttps://www.erlang.org/downloads安装依赖包yuminstallgccglibc-develmakencurses-developenssl-develautoconfyuminstall......
  • Linux部署-Net并配置进程守护
    Linux部署-Net并配置进程守护注册Microsoft签名密钥并添加Microsoft产品提要sudorpm--importhttps://packages.microsoft.com/keys/microsoft.ascsudosh-c'e......
  • Fix error - processing package linux-headers-6.0.0-kali6-amd64 (--configure)
    Fixerror-processingpackagelinux-headers-6.0.0-kali6-amd64(--configure)Issue:Settinguplinux-headers-6.0.0-kali6-amd64(6.0.12-1kali1).../etc/kernel/......
  • Linux学习-DAY7
    2.2接收用户参数Linux系统中的Shell脚本语言内设了用于接收参数的变量,变量之间使用空格间隔。例如,$0对应的是当前Shell脚本程序的名称,$#对应的是总共有几个参数,$*对应的是所......