我试图了解链接和加载的工作方式。我的理解是Unix程序“ ld”包含链接和加载功能。调用gcc时,在预处理,编译和组装之后,将调用链接器,该链接器将所有目标文件和.a文件链接到可执行文件中,并提供了有关如何“连接”共享库的最少说明(此处的正确术语是什么) ?)在运行时。该链接器是ld。
在运行时,我的理解是可执行文件已加载到内存中,尽管我不确定如何执行。我的具体问题如下:
1)共享对象文件是在编译时“链接”的,还是发生了什么呢? 2)在运行时,是否再次调用ld?我如何看到我的可执行文件的证明(在Linux和MacOS上)? 3)共享对象文件在运行时是否被“链接”,或者在运行时从LD_LIBRARY_PATH中的位置读取共享对象时,该过程是否还有另一个词?
谢谢!
答案 0 :(得分:2)
在编译时和运行时都调用ld吗?
否:在 编译或运行时调用ld是 not 。
调用gcc时,经过预处理,编译和组装后,将调用链接器,该链接器将所有目标文件和.a文件链接为可执行文件
大多数中等复杂的程序都使用单独编译和链接步骤。
在编译时,会生成一组可重定位的目标文件(在该步骤中调用预处理,编译和组装)。可以选择将(('9b7rfs', '29sdf dfs fdf sdf', 'http://imgur.com/gallery/SDsGdO7', '29', 'M', 1), ('9b73bj', 'quick brown fox', 'https://i.redd.it/lfhg348cszi11.jpg', '18', 'M', 5), ('9b418d', 'third string', 'https://imgur.com/a/DddTo6E', '36', 'm', 6))
文件归档到归档库(.o
)中。
然后执行一个链接步骤(通常称为“静态链接”,以将该步骤与运行时将发生的“动态加载”区分开来),生成可执行文件或共享库。仅在此步骤被调用libsomething.a
。在Linux上,/usr/bin/ld
是binutils软件包的一部分。
以及有关如何“连接”共享库的最少说明
链接器记录在运行时需要哪些共享库,以及可能需要哪些版本的库或符号。
它还记录应使用哪个运行时加载器来加载所需的共享库。
在运行时,我的理解是可执行文件已加载到内存中,尽管我不确定如何加载。
内核将可执行文件加载到内存中,并检查是否在静态链接时请求了运行时加载程序。如果是这样,则动态加载程序也会 加载到内存中,并将执行控制传递给它(而不是主可执行文件)。
然后,动态加载程序的工作是检查可执行文件,以获取需要其他库的指令,检查是否可以找到正确的版本,将其加载到内存中,并进行安排,使符号解析在主程序之间起作用。可执行文件和共享库。 这是运行时加载步骤,通常也称为动态链接。
动态加载程序可以是操作系统的一部分,但是在Linux上,它是libc的一部分(GLIBC,uClibc和musl都有自己的加载程序)。
答案 1 :(得分:0)
不。 ld就像创建库或exe一样进行链接,ld * .so是加载部分。 ld * .so也是操作系统的一部分,而不是gcc套件afaik。 ld通常是基于gcc的系统上(GNU)binutils的一部分(但例如,通常是基于LLVM的系统中的LLVM lld)
ld * .so在Linux上是ld-linux- {arch} .so.2,在例如Linux上是/libexec/ld-elf.so。 FreeBSD。