linux下dlsym返回的函数地址的具体含义

linux下动态链接的例子有很多,我从网上找到了一个,如下
动态链接示例地址:
https://blog.csdn.net/fuyuande/article/details/82913961

对于main函数,我稍微修改了下,添加了printf打印一些地址

#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>

void main()
{
    
    
    void *handle;
    void (*hello)(void);

    /* 加载libHelloWorld.so */
    handle = dlopen("libHelloWorld.so", RTLD_LAZY);
    if (!handle)
    {
    
    
        printf("open libHelloWorld.so fail\r\n");
        return;
    }
    printf("handle is %p\n", handle);
    /* 引用库提供的symbol,可以是变量也可以是函数 */
    hello = dlsym(handle, "hello");
    if ( !hello )
    {
    
    
        printf("open symbol fail\r\n");
        dlclose(handle);
        return;
    }
    printf("address of hello function is %p\n", hello);
    /* 调用库函数 */
    hello();
    while(1);
    /* 释放库的引用计数 */
    dlclose(handle);
    return;
}

控制台输出的结果如下:
[root@localhost learn]# ./dllib
handle is 0x152a040
address of hello function is 0x7f1898c09665
Hello World

从上面的运行结果看,很明显,是64位的进程。
在windows操作系统下,与dlopen对应的是LoadLibrary函数,LoadLibrary返回的是dll加载于进程虚拟地址空间的地址,具有非常明确的含义。但是linux下的dlopen返回的handle是0x152a040,这个很明显,不是so加载到进程虚拟地址空间的地址。

此进程号为16492,我们使用命令cat /proc/16492/maps,打印结果如下
在这里插入图片描述

此处,我们加载的动态库是libHelloWorld.so,从图中可以看出此动态库加载到进程地址空间的起始地址是7f1898c09000,这个与main函数中打印出的hello函数的地址0x7f1898c09665非常接近,差了一个0x665,这个0x665实际上就是hello函数在动态库libHelloWorld.so里面的偏移地址,可以从nm命令验证这一点,如下所示:
[root@localhost learn]# nm libHelloWorld.so |grep hello
0000000000000665 T hello

所以,跟windows一样,动态库里面函数在内存空间的地址,其实就是动态库在进程空间的地址+此函数在动态库里面的偏移地址。

下面给出动态库libHelloWorld.so的头文件和.c文件代码,以免上面的链接丢失

//实现文件 HelloWorld.c
/**
 *  简单动态库文件使用
 */
#include "HelloWorld.h"
 
void hello(void)
{
    
    
    printf("Hello World \r\n");
    return ;
}
 
//头文件 HelloWorld.h
#include <stdio.h>
 
void hello(void);

猜你喜欢

转载自blog.csdn.net/tusong86/article/details/120391863
今日推荐