linux 概念
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Windows下的.dll文件和Linux下的.so文件
在写代码生成这些文件时,区别在于:
1、.so文件没有入口函数的概念,.dll文件有,但却不是必须的。
2、.so会导出文件中定义的所有符号(主要是函数),.dll只导出指定的函数,指定的
方式有两种
a、用dllexport关键词修饰需要导出的函数
b、在module definition file里面定义要导出的函数
3、.so文件是elf格式的,可以不连接某些静态库,而等应用程序去连接。.dll需要连接静态库
可以动态链接的库,在Windows上是dynamic link library (DLL),在UNIX或Linux上是SharedLibrary。库文件是预先编译链接好的可执行文件,存储在计算机的硬盘上。大多数情况下,
同一时间多个应用可以使用一个库的同一份拷贝,操作系统不需要加载这个库的多个实例。
@DLL文件
可以使用两种方法将公共符号导入到应用程序中或从DLL 导出函数:
1、生成DLL 时使用模块定义(.DEF) 文件。
2、在主应用程序的函数定义中使用__declspec(dllimport) 或__declspec(dllexport) 关键字。
使用.DEF 文件
模块定义(.DEF) 文件是包含一个或多个描述各种DLL 属性的Module 语句的文本文件。如果不使用
__declspec(dllimport) 或__declspec(dllexport) 导出DLL 函数,则DLL 需要.DEF 文件。
可以使用.DEF 文件导入到应用程序中或从DLL 导出。
例如:
LIBRARY "DLL的name"
DESCRIPTION 'DLL的name Windows Dynamic Link Library'
EXPORTS
函数名; Explicit exports can go here
LIBRARY "xxx_dll"
EXPORTS
add PRIVAT
使用__declspec
32 位版的Visual C++ 用__declspec(dllimport) 和__declspec(dllexport) 取代以前在16 位版的
Visual C++ 中使用的__export 关键字。不使用__declspec(dllimport) 也能正确编译代码,
但使用
__declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它
十分清楚函数是否在DLL 中,因此可以生成跳过间接级别的代码,而在跨DLL 边界的函数中通常存在
这些间接代码。但是,必须使用__declspec(dllimport) 才能导入DLL 中使用的变量。
如果有正确的.DEF 文件EXPORTS 节,则不需要__declspec(dllexport)。添加__declspec(dllexport)
是为了提供不使用.DEF 文件从.EXE 或.DLL 导出函数的简单方法。Win32 可移植可执行文件格式旨在
最小化为修改导入而必须访问的页数。为此,它将所有程序的所有导入地址都放在一个称为“导入地址表”
的位置。这使得加载程序在访问这些导入时可以只修改一两页。
例如:
#ifndef LIB_H
#define LIB_H
extern "C" int _declspec(dllexport)add(int x,int y);
#endif
@SO文件
就说一个Java中调用so的问题,假如你在Java程序中要调用一个名叫sample的动态库,即如下:
static { System.loadLibrary("sample"); }
那生成的so文件前面必须加lib(最起码在Redhat中是这样的),即
gcc -o libsample.so -shared -I
最后在Java运行时要记得把动态链接库的路径加进来
java -Djava.library.path=
一、公约
1. 库的命名习惯
一个Linux DLL 有三个不同名字的文件组成
soname 文件
lib + 链接库名字+ .so + .版本号
每当链接库接口改变时都递增版本号。soname 文件其实只是一个符号链接而已,指向他的real name 文件。
real name 文件
lib + 链接库名字+ .so + .版本号.次版本号.发行号
发行号是可选的。该文件包含实际代码。
linker name 文件
lib + 链接库名字+ .so
编译器以这个名字来请求指定的链接库。
当程序在内部列出所需要的链接库时,仅仅使用soname。当你创建一个链接库时,使用real name。安装一个新的链接库时,把它复制到一个DLL文件夹里,然后运行程序ldconfig(8)。ldconfig 检查存在的real name 文件,并且创建指向它的符号链接soname 文件。ldconfig 还做一件事情就是建立cache 文件/etc/ld.so.cache
ldconfig 不会创建linker name 文件,但是一般性linker name 文件在安装链接库的时候创建。linker name 文件也只是一个符号链接,指向最新的soname 文件或real name 文件。建议指向soname 文件,因为当你更新库以后,在编译器链接的时候,一般总是想使用新的库。
2. 库的放置
DLL 必须放置在文件系统的指定位置。多数开源软件遵守GNU 标准:当分发源代码的时候,库默认安装在/usr/local/lib,命令安装在/usr/local/bin。该标准还定义了如何重写这些默认标准以及如何调用安装程序。
Filesystem Hierarchy Standard(FHS) 规定:多数库应安装在/usr/lib,启动时需要的库安装在/lib,非系统库应安装在/usr/local/lib
GNU 标准是针对开发人员的,FHS 是针对发行者的。
二、库是如何被使用的
在基于GNU glibc 的系统上,包括所有linux 系统,ELF 可执行二进制文件的运行自动导致程序加载器被加载并且运行。在linux 下,加载器是/lib/ld-linux.so.X(X是版本号)。然后加载器搜索、加载程序所要使用的动态链接库。
被搜索的文件夹列表保存在文件/etc/ld.so.conf 里。
在程序启动的时候搜索这些文件夹是很没有效率的,所以实际上使用缓存。ldconfig(8) 默认读取/etc/ld.so.conf 文件,在DLL 文件夹里创建合适的符号链接,在/etc/ld.so.cache 里写入一个缓存。缓存大大加速了库的读取。所以,当一个DLL 被添加、删除时,或DLL文件夹被改变时都需要运行ldconfig 程序,当安装了一个新的DLL 时,由软件包管理器自动运