博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dl动态链接文件函数
阅读量:2240 次
发布时间:2019-05-09

本文共 16007 字,大约阅读时间需要 53 分钟。

名称

dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym - programming interface to dynamic linking loader dladdr,dlclose,dlerror,dlopen的,则dlsym,dlvsym - 编程接口以动态连接装载机

Synopsis简介

#include < >#包括< >

void *dlopen(const char *filename , int flag );*无效使用dlopen(常量字符* 文件名 ​​,INT 标志);

char *dlerror(void);的char * dlerror(无效);

void *dlsym(void *handle , const char * symbol );无效*对dlsym(无效* 手柄 ,常量字符* 符号 );

int dlclose(void *handle ); dlclose(* 句柄无效);

Link with-ldl .低密度脂蛋白的链接。

Description描述

The four functionsdlopen (), dlsym (), dlclose (),dlerror () implement the interface to the dynamic linking loader.四大功能使用dlopen(),dlsym(),dlclose(),dlerror()实现该接口的动态链接装载机。

dlerror()dlerror()

The functiondlerror () returns a human readable string describing the most recent error that occurred fromdlopen (), dlsym () or dlclose () since the last call todlerror ().
dlerror()函数返回一个人类可读的字符串描述最近错误的,自上次调用
dlerror()dlopen()
则dlsym()
dlclose()发生。
It returns NULL if no errors have occurred since initialization or since it was last called.如果没有错误发生自初始化,因为它是上次调用,它返回NULL。

dlopen()dlopen()的

The functiondlopen () loads the dynamic library file named by the null-terminated stringfilename and returns an opaque "handle" for the dynamic library.
dlopen()的函数加载动态库文件,以空结尾的字符串
文件名 ​​命名为动态库,并返回一个不透明的“把手”。
If filename is NULL, then the returned handle is for the main program.如果
文件名 ​​是NULL,那么返回的句柄是主程序。
If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname.如果
文件名 ​​中包含斜线(“/”),然后它被解释为路径(相对或绝对)。
Otherwise, the dynamic linker searches for the library as follows (see (8) for further details):否则,如下(见库的动态链接器 (8)为进一步的细节):
o Ø

(ELF only) If the executable file for the calling program contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the directories listed in the DT_RPATH tag are searched. (低频),如果调用程序的可执行文件包含DT_RPATH标签,不包含DT_RUNPATH的标签,然后在DT_RPATH标签中列出的目录搜索。

o Ø

If, at the time that the program was started, the environment variableLD_LIBRARY_PATH was defined to contain a colon-separated list of directories, then these are searched.在该计划的启动时间,如果环境变量LD_LIBRARY_PATH定义包含一个冒号分隔的目录列表,那么这些搜索。(As a security measure this variable is ignored for set-user-ID and set-group-ID programs.) (此变量,作为一项安全措施被忽略的set-user-ID和设置组ID方案。)

o Ø

(ELF only) If the executable file for the calling program contains a DT_RUNPATH tag, then the directories listed in that tag are searched. (低频)如果调用程序的可执行文件包含一个DT_RUNPATH标签,然后在该标签中列出的目录搜索。

o Ø

The cache file/etc/ld.so.cache (maintained by (8)) is checked to see whether it contains an entry forfilename .缓存文件/ etc / ld.so.cache的 (保持 (8))进行检查,看它是否包含一个文件名 ​​的条目。

o Ø

The directories/lib and /usr/lib are searched (in that order).搜索目录/ lib/ usr / lib目录 (按顺序)。

If the library has dependencies on other shared libraries, then these are also automatically loaded by the dynamic linker using the same rules.如果库有依赖于其他共享库,那么这些也自动加载动态连接器使用相同的规则。
(This process may occur recursively, if those libraries in turn have dependencies, and so on.) (这个过程可能会出现递归,如果反过来这些库有依赖关系,并依此类推。)

One of the following two values must be included inflag : 标志必须包含在以下两个值之一:

RTLD_LAZY
RTLD_LAZY
Perform lazy binding.执行懒惰约束力。
Only resolve symbols as the code that references them is executed.唯一的解决,引用中被执行的代码的符号。
If the symbol is never referenced, then it is never resolved.如果符号不会被引用,那么它永远不会被解决。
(Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.) (延迟绑定只执行函数引用;加载库时,总是立即绑定变量的引用。)
RTLD_NOW
RTLD_NOW
If this value is specified, or the environment variableLD_BIND_NOW is set to a nonempty string, all undefined symbols in the library are resolved beforedlopen () returns.如果这个值被指定,或环境变量
LD_BIND_NOW设置为一个非空字符串,库中的所有未定义的符号得到解决之前
,dlopen()的回报。
If this cannot be done, an error is returned.如果这不能做,则返回一个错误。
Zero or more of the following values may also be ORed inflag :零个或多个下列值也可能“或”
RTLD_GLOBAL
RTLD_GLOBAL
The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries.这个库中定义的符号将作出可用象征随后加载的库的决议。
RTLD_LOCAL
RTLD_LOCAL
This is the converse ofRTLD_GLOBAL , and the default if neither flag is specified.这是
RTLD_GLOBAL匡威,默认的,如果没有指定标志。
Symbols defined in this library are not made available to resolve references in subsequently loaded libraries.此库中定义的符号,可用来解决在随后加载的库的引用。
RTLD_NODELETE (since glibc 2.2)
RTLD_NODELETE(因为glibc 2.2)
Do not unload the library duringdlclose ().不要在
dlclose()卸载库。
Consequently, the library's static variables are not reinitialized if the library is reloaded withdlopen () at a later time.因此,图书馆的静态变量不会重新初始化,如果库是
使用 dlopen()重新在稍后的时间。
This flag is not specified in POSIX.1-2001.此标志没有被指定在POSIX.1-2001。
RTLD_NOLOAD (since glibc 2.2)
RTLD_NOLOAD(因为glibc 2.2)
Don't load the library.不加载库。
This can be used to test if the library is already resident (dlopen () returns NULL if it is not, or the library's handle if it is resident).这可以用来测试如果库已经是居民
(dlopen()的返回NULL,如果不是,或库的处理,如果它是居民)。
This flag can also be used to promote the flags on a library that is already loaded.这个标志也可以被用来推动一个已经加载的库的标志。
For example, a library that was previously loaded withRTLD_LOCAL can be reopened with RTLD_NOLOAD | RTLD_GLOBAL .例如,图书馆先前加载
RTLD_LOCAL的可以被重新开放与
RTLD_NOLOAD | RTLD_GLOBAL。
This flag is not specified in POSIX.1-2001.此标志没有被指定在POSIX.1-2001。
RTLD_DEEPBIND (since glibc 2.3.4)
RTLD_DEEPBIND(自的glibc 2.3.4)
Place the lookup scope of the symbols in this library ahead of the global scope.将在全球范围内领先这个库的符号查找范围。
This means that a self-contained library will use its own symbols in preference to global symbols with the same name contained in libraries that have already been loaded.这意味着,自足库将使用自己的符号已经加载的库中的名称相同,其优先于全局符号。
This flag is not specified in POSIX.1-2001.此标志没有被指定在POSIX.1-2001。
Iffilename is a NULL pointer, then the returned handle is for the main program.
如果 filename是一个NULL指针,然后返回的句柄是主程序。
When given todlsym (), this handle causes a search for a symbol in the main program, followed by all shared libraries loaded at program startup, and then all shared libraries loaded bydlopen () with the flag RTLD_GLOBAL .这个句柄
对dlsym()时,会导致搜索主程序,在程序启动时加载的所有共享库的象征,那么所有共享库
通过 dlopen()加载的标志
RTLD_GLOBAL。

External references in the library are resolved using the libraries in that library's dependency list and any other libraries previously opened with theRTLD_GLOBAL flag.库中的外部引用,使用该库的依赖列表和RTLD_GLOBAL标志的任何先前打开的其他库的库解决。If the executable was linked with the flag "-rdynamic" (or, synonymously, "--export-dynamic"), then the global symbols in the executable will also be used to resolve references in a dynamically loaded library.如果可执行文件的挂旗“的rdynamic”(“ - 出口动态”,或同义),然后在可执行文件中的全局符号也可以用来解决动态加载库中的引用。

If the same library is loaded again withdlopen (), the same file handle is returned.如果使用 dlopen()再次被载入同一个库,同一个文件句柄被返回。The dl library maintains reference counts for library handles, so a dynamic library is not deallocated untildlclose () has been called on it as many times as dlopen () has succeeded on it. DL库维护库处理引用计数,所以不释放动态库dlclose(),直到被称为多次使用dlopen()已成功就可以了。The _init () routine, if present, is only called once. _init()例程,如果存在的话,只调用一次。But a subsequent call withRTLD_NOW may force symbol resolution for a library earlier loaded withRTLD_LAZY .但随后与RTLD_NOW的呼叫可能会迫使早些时候与RTLD_LAZY加载库的符号解析。

If dlopen () fails for any reason, it returns NULL.如果dlopen()的任何原因而失败,返回NULL。

dlsym()对dlsym()

The functiondlsym () takes a "handle" of a dynamic library returned by dlopen () and the null-terminated symbol name, returning the address where that symbol is loaded into memory.
对dlsym()函数的动态库
通过 dlopen(返回的“句柄”)和null结尾的符号的名称,返回该符号被加载到内存中的地址。
If the symbol is not found, in the specified library or any of the libraries that were automatically loaded bydlopen () when that library was loaded, dlsym () returns NULL.如果符号没有被发现,在指定库或任何库,自动加载库被加载时,
通过dlopen(),则dlsym()返回NULL。
(The search performed bydlsym () is breadth first through the dependency tree of these libraries.) Since the value of the symbol could actually be NULL (so that a NULL return fromdlsym () need not indicate an error), the correct way to test for an error is to calldlerror () to clear any old error conditions, then call dlsym (), and then call dlerror () again, saving its return value into a variable, and check whether this saved value is not NULL. (执行
对dlsym(搜索)是广度优先通过这些库的依赖关系树。)由于符号的值实际上是空的(所以,从
对dlsym返回NULL()不需要显示一个错误),正确的做法测试错误是调用
dlerror(),以清除任何旧的错误条件,然后
对dlsym()调用,然后再调用
dlerror(),它的返回值保存到一个变量,并检查是否保存的值不为NULL。

There are two special pseudo-handles,RTLD_DEFAULT and RTLD_NEXT .有两个特殊的伪句柄,RTLD_DEFAULTRTLD_NEXT。The former will find the first occurrence of the desired symbol using the default library search order.前者将找到所需的符号使用默认的库搜索顺序中第一次出现。The latter will find the next occurrence of a function in the search order after the current library.后者会找到下一个出现在搜索顺序后,目前图书馆的功能。This allows one to provide a wrapper around a function in another shared library.这允许一个围绕另一个共享库中的函数提供了一个包装。

dlclose()dlclose()

The functiondlclose () decrements the reference count on the dynamic library handlehandle .
dlclose()函数递减的动态库句柄
句柄的引用计数。
If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.如果引用计数下降到零,并没有其他的加载库使用它的符号,然后动态库被卸载。

The functiondlclose () returns 0 on success, and nonzero on error. dlclose()这个函数返回成功0,误差为零。

The obsolete symbols _init() and _fini()过时的符号的_init()和_fini()

The linker recognizes special symbols_init and _fini .链接器识别特殊符号
_init
_fini。
If a dynamic library exports a routine named_init (), then that code is executed after the loading, before dlopen () returns.如果一个动态库导出命名
的_init()例程,然后该代码执行后装车之前
,dlopen()的回报。
If the dynamic library exports a routine named_fini (), then that routine is called just before the library is unloaded.如果动态库导出一个名为
_fini()例程,然后该程序被调用之前卸载库。
In case you need to avoid linking against the system startup files, this can be done by using the (1) -nostartfiles command-line option.如果您需要,以避免对系统启动文件的链接,这可以通过使用 (1)命令行选项
-nostartfiles。

Using these routines, or the gcc-nostartfiles or -nostdlib options, is not recommended.使用这些例程,GCC-nostartfilesnostdlib选项,不推荐。Their use may result in undesired behavior, since the constructor/destructor routines will not be executed (unless special measures are taken).它们的使用可能会导致意外的行为,因为构造/析构函数不会被执行(除非采取特别措施)。

Instead, libraries should export routines using the__attribute__((constructor)) and __attribute__((destructor)) function attributes.相反,图书馆应出口例程使用__ attribute__((构造))__ attribute__((析构函数))函数属性。See the gcc info pages for information on these.看到这些信息的GCC的info页面。Constructor routines are executed beforedlopen () returns, and destructor routines are executed before dlclose () returns.构造函数之前执行dlopen()的返回,和析构函数例程dlclose()返回之前执行。

Glibc extensions: dladdr() and dlvsym()Glibc的扩展:dladdr()和dlvsym()

Glibc adds two functions not described by POSIX, with prototypes Glibc的增加了两个功能不通过POSIX的描述,与原型
#define _GNU_SOURCE /* See  (7) */ #定义_GNU_SOURCE / *  (7)* /#include <  > #包括<  >  int dladdr(void * addr , Dl_info * info ); dladdr(无效 地址 ,Dl_info * 信息 );  void *dlvsym(void * handle , char * symbol , char * version ); 无效* dlvsym(无效* 手柄 ,CHAR * 符号 ,字符* 版本 );
The functiondladdr () takes a function pointer and tries to resolve name and file where it is located.的功能
dladdr()需要一个函数指针,并试图解决的名称和文件位于何处。
Information is stored in theDl_info structure:信息存储在
Dl_info结构:
typedef struct {
typedef结构{
const char *dli_fname; /* Pathname of shared object that常量/ *字符* dli_fname;路径名共享对象 contains address */包含地址* / void *dli_fbase; /* Address at which shared object无效* dli_fbase; / *地址在共享对象 is loaded */加载* / const char *dli_sname; /* Name of nearest symbol with address常量字符* dli_sname; / *最近的地址符号名称 lower than addr */低比地址 * / void *dli_saddr; /* Exact address of symbol named无效* dli_saddr; / *符号的确切地址 in dli_sname */ *在dli_sname的 /} Dl_info; } Dl_info;
If no symbol matchingaddr could be found, then dli_sname and dli_saddr are set to NULL.如果没有匹配
地址的符号,可以发现,,然后
dli_sname
dli_saddr设置为NULL。

dladdr () returns 0 on error, and nonzero on success.dladdr()返回0的错误,并成功返回非零值。

The functiondlvsym (), provided by glibc since version 2.1, does the same asdlsym () but takes a version string as an additional argument.作为对dlsym()相同的功能dlvsym(),自2.1版本的glibc提供的,确实,但作为一个额外的参数版本字符串。

Conforming To符合

POSIX.1-2001 describesdlclose (), dlerror (), dlopen (), anddlsym (). POSIX.1-2001介绍dlclose(),dlerror()dlopen()的, dlsym()。

Notes笔记

The symbolsRTLD_DEFAULT and RTLD_NEXT are defined by < > only when_GNU_SOURCE was defined before including it.符号RTLD_DEFAULTRTLD_NEXT的定义<只有当_GNU_SOURCE之前,包括它的定义。

Since glibc 2.2.3, (3) can be used to register an exit handler that is automatically called when a library is unloaded.因为glibc 2.2.3, (3)可以用来登记库被卸载时,它会自动调用退出处理。

History历史

The dlopen interface standard comes from SunOS. dlopen的接口标准,从SunOS。
That system also hasdladdr (), but not dlvsym ().该系统还具有
dladdr(),但不
dlvsym()。

Bugs错误

Sometimes, the function pointers you pass todladdr () may surprise you.有时,函数指针传递到dladdr()可能会令你大吃一惊。On some architectures (notably i386 and x86_64),dli_fname and dli_fbase may end up pointing back at the object from which you calleddladdr (), even if the function used as an argument should come from a dynamically linked library.在某些体系结构(特别是i386和x86_64),dli_fnamedli_fbase可能最终指向的对象,从中你叫dladdr()回来,即使作为一个参数使用的功能应该从动态链接库。

The problem is that the function pointer will still be resolved at compile time, but merely point to theplt (Procedure Linkage Table) section of the original object (which dispatches the call after asking the dynamic linker to resolve the symbol).函数指针仍然会在编译时解决问题,但只是指向原来的对象(其中调度呼叫后要求动态连接器解析符号)PLT(过程链接表)节。To work around this, you can try to compile the code to be position-independent: then, the compiler cannot prepare the pointer at compile time anymore and today's (1) will generate code that just loads the final symbol address from thegot (Global Offset Table) at run time before passing it to dladdr ().要解决这个问题,你可以尝试要编译的代码是位置无关:那么,编译器不能在编译时准备的指针不再与今天的 (1)将生成的代码,只是加载 GOT的最终符号地址(在运行时全局偏移表),然后将它传递给dladdr()。

Example例子

Load the math library, and print the cosine of 2.0:加载的数学库,并​​打印2.0的余弦:

#include <  >的#include <  >#include <  > #包括<  >#include <  > #包括<  >int INTmain(int argc, char **argv)主(INT,CHAR ** ARGV ARGC){
{
void *handle;无效处理; double (*cosine)(double);双(余弦)(双); char *error;字符*错误; handle = dlopen("libm.so", RTLD_LAZY);处理=使用dlopen(“libm.so”,RTLD_LAZY); if (!handle) {
(手柄){
fprintf(stderr, "%s\n", dlerror());与fprintf(STDERR,“%S \ N”,dlerror()); exit(EXIT_FAILURE);出口(EXIT_FAILURE); } } dlerror(); /* Clear any existing error */ dlerror(); / *清除任何现有的错误* / /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos"); / *写作:余弦=(双(*)(双))对dlsym(处理,“COS”); would seem more natural, but the C99 standard leaves似乎更自然,但C99标准的叶子 casting from "void *" to a function pointer undefined.从“无效*”函数指针未定义的铸造。 The assignment used below is the POSIX.1-2003 (Technical使用下面的赋值是的POSIX.1-2003(技术 Corrigendum 1) workaround; see the Rationale for the勘误表1)解决方案;见的理由 POSIX specification of dlsym(). POSIX规范对dlsym()。 */ * / *(void **) (&cosine) = dlsym(handle, "cos");无效*(**)(&余弦)= dlsym进行(处理,“COS”); if ((error = dlerror()) != NULL) {
((错误= dlerror())!= NULL){
fprintf(stderr, "%s\n", error);与fprintf(STDERR,“%S \ N”,错误); exit(EXIT_FAILURE);出口(EXIT_FAILURE); } } printf("%f\n", (*cosine)(2.0)); printf(“请%F \ N”(余弦)(2.0)); dlclose(handle); dlclose(句柄); exit(EXIT_SUCCESS);出口(EXIT_SUCCESS);} }
If this program were in a file named "foo.c", you would build the program with the following command:如果这项计划名为“foo.c的”文件,你会用下面的命令建立程序:
gcc -rdynamic -o foo foo.c -ldl富foo.c的GCC-rdynamic-O-LDL
Libraries exporting_init () and _fini () will want to be compiled as follows, usingbar.c as the example name:图书馆出口
的_init()
_fini()将要被编 ​​译如下,使用
bar.c例如名称为:
gcc -shared -nostartfiles -o bar bar.c GCC共享nostartfiles的-O栏的差异套用至工作复本路径

转载地址:http://uoqbb.baihongyu.com/

你可能感兴趣的文章
Oracle数据库中的(+)连接
查看>>
java-oracle中几十个实用的PL/SQL
查看>>
PLSQL常用方法汇总
查看>>
几个基本的 Sql Plus 命令 和 例子
查看>>
PLSQL单行函数和组函数详解
查看>>
Oracle PL/SQL语言初级教程之异常处理
查看>>
Oracle PL/SQL语言初级教程之游标
查看>>
Oracle PL/SQL语言初级教程之操作和控制语言
查看>>
Oracle PL/SQL语言初级教程之过程和函数
查看>>
Oracle PL/SQL语言初级教程之表和视图
查看>>
Oracle PL/SQL语言初级教程之完整性约束
查看>>
PL/SQL学习笔记
查看>>
如何分析SQL语句
查看>>
结构化查询语言(SQL)原理
查看>>
SQL教程之嵌套SELECT语句
查看>>
日本語の記号の読み方
查看>>
计算机英语编程中一些单词
查看>>
JavaScript 经典例子
查看>>
判断数据的JS代码
查看>>
js按键事件说明
查看>>