windows及linux链接库 – 作者:夏鸥兔兔2000

一.链接库

1.静态链接库

1.1 windows(.lib)

在计算机科学里,静态库(英语:Static library, Statically-linked library),或称静态库,是一个外部函数与变量的共同体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,其内容不像动态链接库那么复杂,在编译期间由编译器与连接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。

例子一:为什么不用.cpp文件直接对工程进行链接,因为这样会泄露代码,而如果使用链接库的时候,就可以不会把代码泄露给别人。

例子二:静态链接库不同于动态链接库,静态链接库直接把库放到了exe可执行文件中。

1.2 linux(.a)

在linux中编译c++的时候,使用了gcc进行编译,可以生成.o的目标文件,使用:

gcc -c test.c

//生成了.o的文件

使用ar命令将生成的.o文件生成为.a的静态链接库文件:

ar的命令:
c -- 如果库文件不存在,生成新的库文件,并不打印警告
r -- 代替库中已有的文件或者插入新的文件
v -- 输出详细信息
d -- 删除库中的某个目标文件
t -- 列出归档文件中包含的目标文件

//这里我们使用的是rcv参数

ar rcv libtest.a test.o
//生成了.a的静态连接库

将我们生成的静态链接库可以链接到某个c程序的使用。

gcc main.c -L. -ltest

//当我们链接时,指定 -lxxx,链接器就会在指定的目录查找 libxxx.a 或 libxxx.so 文件

这里我们进行一个完整的静态链接库的编写:

图片[1]-windows及linux链接库 – 作者:夏鸥兔兔2000-安全小百科

代码:

# sub.cpp
int sub(int a, int b)
{
return a - b;
}


#sub.h
#pragma once
int sub(int a, int b);


#main.cpp
#include<stdio.h>
#include"sub.h"
int main()
{
printf("%d", sub(9, 4));
return 0;
}

2.动态链接库

2.1windows

DLL:Dynamic Link Library,即动态链接库,这种库包含了可由多个程序同时使用的代码和数据。

它是microsoft在windows操作系统中实现共享函数库概念的一种实现方式。

DLL最初用于节约应用程序所需要的磁盘和内存空间。早前,在传统的非共享库中,一部分代码简单地附加到调用的程序中。如果两个程序同时调用同一个子程序,就会出现两份那段代码。相反,许多应用共享的代码能够切分到一个DLL中,在硬盘上存为一个文档,在内存中只需使用一个实例。

当某个程序或 DLL 在另一个 DLL 中使用 DLL 函数时,将创建一个依赖项。 因此,该程序不再是独立的,如果依赖项断开,该程序可能会遇到问题。 例如,如果发生下列操作之一,则该程序可能无法运行:

  • 依赖 DLL 升级到新版本。

  • 固定的 DLL 是固定的。

  • 早期版本会覆盖依赖 DLL。

  • 将从计算机中删除依赖 DLL。

以下列表介绍了 Windows 2000 和更高版本的 Windows 操作系统中引入的更改,以帮助最大限度地减少依赖性问题:

  • Windows 文件保护

    在 Windows 文件保护中,操作系统可防止未经授权的代理更新或删除系统 Dll。 因此,当程序安装尝试删除或更新定义为系统 DLL 的 DLL 时,Windows 文件保护将查找有效的数字签名。

  • 专用 Dll

    专用 Dll 允许您将程序与对共享 Dll 所做的更改隔离。 专用 Dll 使用版本特定的信息或一个空的本地文件来强制实施该程序使用的 DLL 版本。 若要使用专用 Dll,请在程序根文件夹中找到您的 Dll。 然后,对于新程序,向 DLL 中添加版本特定的信息。 对于旧程序,请使用空的本地文件。 每个方法都通知操作系统使用位于程序根文件夹中的专用 Dll。

查找顺序:

  • 假如安全DLL搜索模式启用,搜索顺序如下:

  • 应用程序所在的路径

  • Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。

  • 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。

  • Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。

  • 当前目录

  • PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

//应用程序所在目录→当前目录→Windows SYSTEM目录→Windows目录→PATH环境变量指定的路径

假如安全DLL搜索模式禁用,搜索顺序如下:

  • 应用程序所在的路径

  • 当前目录

  • Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。

  • 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。

  • Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。

  • PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

2.2linux

Linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

编写动态链接库:

  1. 编写源文件

  2. 将一个或几个源文件编译链接,生成共享库。

  3. 通过 -L<path>-lxxx 的gcc选项链接生成的libxxx.so。

  4. 把 libxxx.so 放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

gcc -fPIC -c add.c sub.c
//编译为.o文件
//其中,PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性

gcc -shared -o libmymath.so sub.o add.o
//链接,把两个.o文件生成为一个.so文件(动态链接库)
//-shared是链接选项,告诉gcc生成动态库而不是可执行文件

但是生成后运行出错,原因:

对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索:

  1. elf文件的DT_RPATH段

  2. 环境变量LD_LIBRARY_PATH

  3. /etc/ld.so.cache文件列表

  4. /lib/

  5. /usr/lib

找到库文件后将其载入内存。

所以,我们想让程序找到自己写的动态链接库,有如下方法:

  • 指定 LD_LIBRARY_PATH 环境变量为 libmymath.so 文件所在的目录

  • 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径; 同时,运行ldconfig ,该命令会重建/etc/ld.so.cache文件

  • 把 libmymath.so 拷贝到/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作

图片[2]-windows及linux链接库 – 作者:夏鸥兔兔2000-安全小百科

来源:freebuf.com 2020-11-12 09:31:35 by: 夏鸥兔兔2000

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论