Linux 动态库更新需要注意的坑

  linux VFS快速入门,请参考我的博客如何在linux添加一个最简单的自己写的文件系统。源码今日头条,视频演示https://m.toutiaoimg.com/i6753964400429761031/?gd_ext_json=%7B%22enter_from%22%3A%22click_creation_center%22%2C%22category_name%22%3A%22creation_center%22%7D&enter_from=click_creation_center&category_name=creation_center&share_token=19b860f8-843e-4c8b-adfa-b6e3aa083c2b&tt_from=copy_link&utm_source=copy_link&utm_medium=toutiao_android&utm_campaign=client_share?=

     参考上述,可快速了解vfs数据结构(比如inode和文件的关系,dentry,super_block等)及VFS API的使用。

      以cdds_service、cdds动态库、cdds_bag举例。有同事在更新cdds动态库的时候,经常没有全部杀光调用了cdds动态库API的进程。比如cdds_service在运行,这个时候更新动态库(这样操作,动态库文件的inode不会发生改变),然后再启动cdds_bag,这个时候cdds_bag还会使用内存中缓冲的cdds动态库,导致cdds_bag crash,或其他各种诡异问题。如下图所示,动态库cdds_mm的inode没有发生改变。动态库的加载流程是open→mmap。由于inode没有发生改变,而且内存中缓冲有动态库文件,这个时候将导致新启动的进程将使用内存中缓冲的就动态库。如果新动态库API发生了改变,比如参数改变,这会导致各种诡异问题。

 

<think>嗯,用户想了解如何在动态库中使用某些功能或进行操作,特别是动态库的使用方法、示例和说明。我需要先理清动态库的基本概念,然后逐步介绍具体的使用步骤。 首先,动态库是什么?动态库在程序运行时被加载,多个程序可以共享同一个库的代码,这样可以节省内存和磁盘空间。常见的后缀有.so(Linux)和.dll(Windows)。这点在用户提供的引用[1]中提到了,可以引用过来。 接下来,用户需要知道如何使用动态库。可能需要分步骤说明,比如生成动态库、动态加载和使用。生成动态库的话,在Linux下用gcc编译,参数-fPIC和-shared是关键,如引用[4]中的示例。这部分需要详细说明编译命令和步骤。 然后是动态加载的过程。在C/C++中,使用dlopen、dlsym等函数来动态加载库,并获取函数指针。引用[2]提到了动态加载的方法,可以结合里面的内容,给出代码示例。比如打开库、获取函数、调用函数、关闭库的流程。 另外,用户可能需要不同平台的示例,比如Linux和Windows的区别。比如Windows下使用LoadLibrary和GetProcAddress,而Linux用dlopen。需要分别说明,并指出头文件和链接库的差异,如引用[3]中的生成动态库部分。 还要注意错误处理,比如检查函数指针是否为空,避免程序崩溃。同时,在代码示例中加入错误处理的步骤,这样用户能更安全地使用动态库。 用户提供的引用中有Python调用C动态库的示例,可能也需要补充这部分。比如使用ctypes模块加载.so文件,并调用其中的函数。这样可以展示不同语言间的互操作性,增加实用性。 最后,常见问题部分需要涵盖路径问题、函数签名一致性和跨平台问题,这些都是用户在实际使用中可能遇到的,提前说明能帮助他们避免错误。 确保整个回答结构清晰,分步骤讲解,代码示例正确,并且引用相关的资料。检查LaTeX格式是否正确,数学公式用$包裹,独立公式用$$。同时生成相关问题,比如不同平台的区别、动态加载的优势、错误处理等,帮助用户进一步学习。</think>### 动态库的使用方法与示例说明 #### 一、动态库基础概念 动态库(Dynamic Library)是程序运行时加载的共享代码库,以`.so`(Linux)或`.dll`(Windows)为后缀。其核心优势在于**代码复用**和**内存节省**,多个程序可共享同一动态库[^1]。 --- #### 二、动态库使用步骤 ##### 1. **生成动态库** 以Linux平台为例,使用`gcc`编译生成动态库: ```bash # 编译为目标文件(-fPIC生成位置无关代码) gcc -c -fPIC mylib.c -o mylib.o # 生成动态库(-shared表示生成共享库) gcc -shared mylib.o -o libmylib.so ``` 若需导出所有函数,需在头文件中声明`extern "C"`(避免C++名称修饰)[^3]。 ##### 2. **动态加载动态库** 动态加载的核心是通过`dlopen`(Linux)或`LoadLibrary`(Windows)实现**运行时链接**,示例如下: ###### **Linux示例(C/C++)** ```cpp #include <dlfcn.h> int main() { // 加载动态库(RTLD_LAZY表示延迟绑定) void* handle = dlopen("./libmylib.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); return 1; } // 获取函数指针(假设库中有函数int add(int, int)) typedef int (*AddFunc)(int, int); AddFunc add = (AddFunc)dlsym(handle, "add"); if (!add) { fprintf(stderr, "%s\n", dlerror()); dlclose(handle); return 1; } // 调用函数 int result = add(2, 3); printf("Result: %d\n", result); // 关闭动态库 dlclose(handle); return 0; } ``` 编译时需链接`-ldl`: ```bash gcc main.c -ldl -o main ``` ###### **Windows示例(C/C++)** ```cpp #include <windows.h> int main() { // 加载动态库 HINSTANCE hDll = LoadLibrary("mylib.dll"); if (!hDll) { printf("LoadLibrary failed\n"); return 1; } // 获取函数地址 typedef int (*AddFunc)(int, int); AddFunc add = (AddFunc)GetProcAddress(hDll, "add"); if (!add) { printf("GetProcAddress failed\n"); FreeLibrary(hDll); return 1; } // 调用函数 int result = add(2, 3); printf("Result: %d\n", result); // 释放动态库 FreeLibrary(hDll); return 0; } ``` ##### 3. **Python调用动态库** 通过`ctypes`模块实现: ```python from ctypes import CDLL, c_int # 加载动态库 lib = CDLL('./libmylib.so') # 定义参数和返回类型(若需要) lib.add.argtypes = [c_int, c_int] lib.add.restype = c_int # 调用函数 result = lib.add(2, 3) print(f"Result: {result}") # 输出:Result: 5 ``` 注意:需确保函数签名与Python类型匹配[^4]。 --- #### 三、关键注意事项 1. **路径问题**:动态库需位于系统库路径(如`/usr/lib`)或指定相对/绝对路径。 2. **函数签名一致性**:调用时需严格匹配参数和返回值类型。 3. **跨平台差异**:Windows使用`__declspec(dllexport)`导出函数,Linux默认导出所有符号。 --- #### 四、应用场景 - **插件系统**:动态加载不同功能模块(如浏览器插件)[^2] - **热更新**:替换动态库文件实现功能升级 - **依赖解耦**:第三方库以动态形式集成 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无v邪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值