linux 动态链接库初始化
时间: 2023-12-09 16:00:59 浏览: 83
在Linux中,动态链接库的初始化通常是通过动态链接器(ld.so)来完成的。
当一个程序使用到了某个动态链接库时,操作系统会使用动态链接器来加载和初始化该库。动态链接器会检查程序中对该库的引用,并根据指定的搜索路径来查找库文件。一旦找到库文件,动态链接器会将该库加载到进程的虚拟地址空间中。
动态链接器在加载和初始化动态链接库时,会执行以下几个步骤:
1. 打开库文件:动态链接器会使用系统调用(如open)打开库文件,以便读取和加载库中的代码和数据。
2. 解析符号:动态链接器会解析库中的符号。这包括解析库中所有的函数和全局变量的地址,并将其与程序中对应的符号进行匹配。
3. 分配空间:动态链接器会为库代码和全局变量分配内存空间,并将其加载到进程的虚拟地址空间中。
4. 修复引用:动态链接器会修改程序中对库的符号的引用,使其指向在内存中的正确地址。
5. 执行初始化:动态链接器会执行库的初始化函数,进行一些初始化操作,例如初始化全局变量、注册回调等。
6. 设置共享:动态链接器会将库设置为共享状态,这样其他进程也可以使用该库。
通过以上步骤,动态链接器能够成功地加载和初始化动态链接库,使得程序能够正确地使用库中提供的功能和资源。动态链接库的使用不仅可以减小程序的体积,还可以提供代码的复用和维护的便利性。
相关问题
linux中动态库加载时调用某个函数
在Linux中,动态库加载时可以通过使用构造函数(constructor)或动态链接器指定的初始化函数来调用某个函数。这样可以在动态库加载时执行一些额外的代码。
使用构造函数的方法是在动态库中定义一个特殊的函数,编译器会在动态库加载时自动调用这个函数。构造函数的命名规则为`__attribute__((constructor))`后跟函数名。例如:
```c
#include <stdio.h>
void my_constructor() __attribute__((constructor));
void my_constructor() {
printf("Hello from constructor!\n");
}
```
在上面的例子中,`my_constructor`函数被定义为构造函数。当动态库被加载时,该函数会自动被调用。
另一种方法是使用动态链接器(ld.so)指定的初始化函数。可以通过使用`__attribute__((constructor))`来标记一个函数作为初始化函数。例如:
```c
#include <stdio.h>
void my_init() __attribute__((constructor));
void my_init() {
printf("Hello from init function!\n");
}
```
在上面的例子中,`my_init`函数被定义为初始化函数。当动态库被加载时,动态链接器会自动调用该函数。
需要注意的是,构造函数和初始化函数的执行顺序是不确定的,因此在动态库中使用这些函数时应谨慎。
so共享库自带的初始化和范厨师
在 Linux 系统中,动态链接库(共享库)可以定义自己的初始化和清理函数,它们会在动态链接库加载和卸载时自动调用。
初始化函数的名称为 `_init`,其原型为:
```c
void _init(void);
```
清理函数的名称为 `_fini`,其原型为:
```c
void _fini(void);
```
当动态链接库加载时,动态链接器会自动调用 `_init` 函数;当动态链接库卸载时,动态链接器会自动调用 `_fini` 函数。
下面是一个简单的示例,演示如何在动态链接库中定义初始化和清理函数:
test.c 文件:
```c
#include <stdio.h>
__attribute__((constructor)) void init_func()
{
printf("test.so initialized\n");
}
__attribute__((destructor)) void uninit_func()
{
printf("test.so uninitialized\n");
}
void test_func()
{
printf("test_func called\n");
}
```
在上述代码中,我们使用 GCC 的 `__attribute__((constructor))` 和 `__attribute__((destructor))` 属性,分别将 `init_func` 和 `uninit_func` 函数定义为初始化函数和清理函数。在 `init_func` 函数中输出初始化信息,在 `uninit_func` 函数中输出清理信息。同时,我们定义了一个 `test_func` 函数,用于在主程序中调用。
编译命令:
```
gcc -shared -fPIC -o libtest.so test.c
```
在主程序中加载动态链接库,并调用其中的函数:
```c
#include <dlfcn.h>
int main()
{
void *handle = dlopen("./libtest.so", RTLD_NOW);
if (handle == NULL) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
return 1;
}
void (*test_func)();
test_func = (void (*)())dlsym(handle, "test_func");
if (test_func == NULL) {
fprintf(stderr, "dlsym failed: %s\n", dlerror());
dlclose(handle);
return 1;
}
test_func();
dlclose(handle);
return 0;
}
```
在上述代码中,我们使用 dlopen() 函数加载动态链接库,并使用 dlsym() 函数获取其中的函数指针。然后,我们调用动态链接库中的函数,完成相应的操作。在程序结束时,动态链接器会自动调用 `_fini` 函数来清理动态链接库。