1.linux的.ko与.so文件
2.一种简单加载vulkan动态库的方法
3.Linux cè°ç¨so
4.动态链接库查找路径全面解析,与undefined symbol说再见
5.Linux下通过execl启动另一个程序,如何加载动态库?
linux的.ko与.so文件
在Linux系统中,.ko文件代表内核对象文件(Kernel Object),它是将内核功能移动至内核之外,需要时插入内核,deepzip源码怎么使用不需要时卸载的一种方式。这种设计有两大优势:一是可以减小内核体积,二是使用方便。加载内核模块可通过两种方法实现:直接使用insmod命令执行加载操作,或先将模块拷贝至特定目录(基于内核版本的/lib/module/#uname-r#/),接着运行depmod生成依赖关系文件,最后调用modprobe进行加载。加载驱动模块后,通过lsmod命令查看已加载模块列表,游泳端梦幻源码使用rmmod命令卸载。与.so文件相比,.ko文件专门用于内核扩展功能。
.so文件则与C语言的动态链接库(Dynamic Link Library)相关联。在C语言编程中,动态库调用有两种主要方式:一种类似静态库调用,即通过头文件直接调用库中函数,程序启动时加载库文件;另一种则是通过dlopen和dlsym函数动态加载库,无需直接调用头文件,程序执行到指定位置时加载库文件。这种方式下,不需要在编译时指定库文件位置和名称,但在代码中需使用dlopen加载库,并使用dlsym根据符号查找函数地址。合肥源码网这两种方式各有优势,可根据项目需求灵活选择。
一种简单加载vulkan动态库的方法
在适配国产Linux环境的vulkan应用时,常需面对系统自带libvulkan.so.1但缺失libvulkan.so的困境。若系统源缺少vulkan SDK或loader,需手工下载并编译,步骤繁琐且涉及依赖安装与CMake升级。为简化流程,实现快速测试vulkan兼容性和调试应用,本文提出一种简易加载vulkan动态库的方法,无需安装vulkan SDK或loader,直接利用系统中自带的libvulkan.so.1。
基本原理在于初始化阶段,通过dlopen和dlsym加载vulkan动态库中的免费下载付费源码api函数指针,应用程序直接调用这些api。本文采用了一个开源的动态库加载工具dylib,支持多系统平台。以vkCreateInstance函数地址的加载为例,需注意vkCreateInstance在vulkan_core.h中的声明被宏VK_NO_PROTOTYPES括起。在CMake中添加该宏定义(add_definitions(-DVK_NO_PROTOTYPES)),阻止vulkan_core.h对原生vk api进行声明。这样,可在load.h中对原生vulkan api进行声明,实现动态库加载。
整个load.h源码示例如下,应用于app初始化时调用vk_loader_init(),实现vulkan动态库中所有函数地址的加载。测试demo项目的软件库源码会员地址提供于此。
Linux cè°ç¨so
å®ä¾ä»£ç ï¼soTest.cï¼ï¼
1 #include <stdio.h>
2 #include <dlfcn.h>
3
4 int main(int argc, char *argv[]){
5 void * libm_handle = NULL;
6 float (*cosf_method)(float);
7 char *errorInfo;
8 float result;
9
// dlopen å½æ°è¿ä¼èªå¨è§£æå ±äº«åºä¸çä¾èµé¡¹ãè¿æ ·ï¼å¦ææ¨æå¼äºä¸ä¸ªä¾èµäºå ¶ä»å ±äº«åºç对象ï¼å®å°±ä¼èªå¨å è½½å®ä»¬ã
// å½æ°è¿åä¸ä¸ªå¥æï¼è¯¥å¥æç¨äºåç»ç API è°ç¨
libm_handle = dlopen("libm.so", RTLD_LAZY );
// å¦æè¿å NULL å¥æï¼è¡¨ç¤ºæ æ³æ¾å°å¯¹è±¡æ件ï¼è¿ç¨ç»æãå¦åçè¯ï¼å°ä¼å¾å°å¯¹è±¡çä¸ä¸ªå¥æï¼å¯ä»¥è¿ä¸æ¥è¯¢é®å¯¹è±¡
if (!libm_handle){
// å¦æè¿å NULL å¥æ,éè¿dlerroræ¹æ³å¯ä»¥åå¾æ æ³è®¿é®å¯¹è±¡çåå
printf("Open Error:%s.\n",dlerror());
return 0;
}
// ä½¿ç¨ dlsym å½æ°ï¼å°è¯è§£ææ°æå¼ç对象æ件ä¸ç符å·ãæ¨å°ä¼å¾å°ä¸ä¸ªææçæå该符å·çæéï¼æè æ¯å¾å°ä¸ä¸ª NULL 并è¿åä¸ä¸ªé误
cosf_method = dlsym(libm_handle,"cosf");
errorInfo = dlerror();// è°ç¨dlerroræ¹æ³ï¼è¿åé误信æ¯çåæ¶ï¼å åä¸çé误信æ¯è¢«æ¸ 空
if (errorInfo != NULL){
printf("Dlsym Error:%s.\n",errorInfo);
return 0;
}
// æ§è¡âcosfâæ¹æ³
result = (*cosf_method)(0.0);
printf("result = %f.\n",result);
// è°ç¨ ELF 对象ä¸çç®æ å½æ°åï¼éè¿è°ç¨ dlclose æ¥å ³é对å®ç访é®
dlclose(libm_handle);
return 0;
}
å¨è¿ä¸ªä¾åä¸ä¸»è¦æ¯è°ç¨äº math åºï¼libm.soï¼ä¸çâcosfâå½æ°ï¼dlopenå½æ°ç第äºä¸ªåæ°è¡¨ç¤ºå è½½åºæ件ç模å¼ï¼ä¸»è¦æ两ç§ï¼RTLD_LAZY æç¼å³å®ï¼çæéè¦æ¶å解åºç¬¦å·ï¼RTLD_NOW ç«å³å³å®ï¼è¿åå解é¤æææªå³å®ç符å·ãå¦å¤è®°å¾å¼ç¨å å«APIç头æ件â#include <dlfcn.h>âï¼^_^ï¼ã
动态链接库查找路径全面解析,与undefined symbol说再见
在编译、运行大型项目时,"undefined symbol"报错是最常见且棘手的问题。这类问题涉及调整多种环境变量和配置文件,如LD_LIBRARY_PATH、LDFLAGS、LIBRARY_PATH、ldconfig等。大型项目编译耗时,调整环境配置仿佛在无尽等待中徘徊,希望某次调整能成功编译。
本文以GNU linker(Linux的ld命令)为例,深入解析动态链接库查找路径的细节,并针对编译与运行场景,提供SEARCH_DIR和/etc/ld.so.cache的解决方案。
在编译过程,动态链接库用于构建程序,ld命令通过链接库找到目标库文件。例如,使用`ld -lcudart`时,需要libcudart.so存在。确保链接器能找到此文件的关键在于指定路径,如`ld -L/path1 -lcudart`。通过`ld -L/path1 -lcudart --verbose`命令查看详细过程,主要关注包含SEARCH_DIR的预定义路径和链接器尝试查找的过程。
链接器查找动态链接库路径的详细信息可参考Linux官方网站,该网站提供ld的权威信息。此外,理解LDFLAGS、LIBRARY_PATH和LD_LIBRARY_PATH等环境变量对链接器的影响也是关键。LDFLAGS由项目开发者传递给编译器,LIBRARY_PATH由编译器传递给链接器,而LD_LIBRARY_PATH对动态库查找影响较小。
在编译阶段,链接器预定义的查找路径是固定且不可配置的,如果项目配置不当,即使调整了环境变量,仍可能遇到问题。若多次尝试无果,考虑将要找的libxxx.so路径软链接到链接器预定义路径中。这样,无论项目配置如何,链接器最终都会搜索到该路径。
运行时,动态链接库查找由Linux库函数dlopen负责。若运行时遇到"undefined symbol"问题,调整`LD_LIBRARY_PATH`环境变量即可。若不想频繁定义环境变量,可修改`/etc/ld.so.conf`和`/etc/ld.so.conf.d/`配置文件,并使用`ldconfig`命令更新`/etc/ld.so.cache`。
总结,LIBRARY_PATH用于控制编译时链接器查找路径,LD_LIBRARY_PATH用于控制运行时查找动态链接库路径。遇到问题时,考虑在编译时将路径软链接到链接器预定义路径,或在运行时更新`/etc/ld.so.cache`。通常情况下,确保配置正确,避免频繁调整,以避免影响其他用户。
若使用NVIDIA维护的conda版本的cuda开发套件,通过`conda install cuda -c "nvidia/label/cuda-.8.0"`下载全套cuda开发工具,`${ CONDA_PREFIX}/lib/`包含动态链接库,如libcudart.so,`${ CONDA_PREFIX}/bin/`包含可执行文件,如nvcc。确保在使用CUDA版本时,理解其动态链接库的多重符号链接(如libcudart.so、libcudart.so.等),有助于彻底解决"undefined symbol"问题。
希望本文内容能帮助大家解决"undefined symbol"问题,彻底告别困扰。
Linux下通过execl启动另一个程序,如何加载动态库?
没看明白问题
如果是被调程序加载动态库,那是自动的,由主调进程环境变量决定。
如果是主调程序加载动态库,则需dlopen打开文件,dlsym按符号获取映射地址,也就是函数或全局数据地址。