- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 dlopen
动态加载库,然后使用 dlclose
关闭它。我希望在 dlclose
完成后释放所有库资源,但在 dlclose
调用之后,库中仍有打开的文件描述符。我想知道如何确保在程序执行过程中卸载库,以便清理所有资源。
我的代码如下:
#include <CL/cl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_PATH_LENGTH 80
int deviceQ()
{
cl_int ret;
void * libHandle = dlopen("/usr/lib64/libOpenCL.so", RTLD_LAZY);
cl_int (* clGetPlatformIDs)(cl_uint, cl_platform_id*, cl_uint*) = dlsym(
libHandle, "clGetPlatformIDs"
);
cl_int (* clGetDeviceIDs)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*) =
dlsym(libHandle, "clGetDeviceIDs");
/********************** PREAMBLE **************************************/
cl_device_id device_id = NULL;
cl_platform_id platform_id = NULL;
cl_uint ret_num_devices;
cl_uint ret_num_platforms;
ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
if (ret != CL_SUCCESS) {
perror("Failed to get platform IDs");
} else if (ret_num_platforms != 1) {
fprintf(stderr, "Number of platforms returned is %d\n", ret_num_platforms);
exit(1);
}
printf("Read platform IDs\n");
ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id,
&ret_num_devices);
if (ret != CL_SUCCESS) {
perror("Failed to get device IDs");
} else if (ret_num_devices != 1) {
fprintf(stderr, "Number of returned devices is %d\n", ret_num_devices);
exit(1);
}
printf("Read device IDs\n");
/********************** PREAMBLE **************************************/
/***************** RELEASE AND FREE ****************************/
dlclose(libHandle);
/***************** RELEASE AND FREE ****************************/
return 0;
}
size_t closeFileDescriptors(void ** arr) {
// step 1 - get PID
pid_t pid = getpid();
//printf("PID is %d\n", pid);
char path[MAX_PATH_LENGTH];
memset(path, '\0', MAX_PATH_LENGTH);
sprintf(path, "/proc/%d/fd", pid);
int fd;
DIR * d = opendir(path);
struct dirent *dir;
struct stat s;
char dirPath[MAX_PATH_LENGTH];
char realPath[MAX_PATH_LENGTH];
size_t index = 0;
if (d) {
while ((dir = readdir(d)) != NULL) {
if (strcmp(dir->d_name, ".") != 0 &&
strcmp(dir->d_name, "..") != 0) {
fd = atoi(dir->d_name);
if (fstat(fd, &s) != 0) {
perror("fstat failed");
}
memset(dirPath, '\0', MAX_PATH_LENGTH);
strcpy(dirPath, path);
strcat(dirPath, "/");
strcat(dirPath, dir->d_name);
#ifdef S_IFLNK
if (s.st_mode & S_IFLNK) {
#else
if (S_ISLNK(s.st_mode)) {
#endif
memset(realPath, '\0', MAX_PATH_LENGTH);
#ifdef readlink
readlink(dirPath, realPath, MAX_PATH_LENGTH);
printf("%s -> %s\n", dirPath, realPath);
#else
printf("[readlink not defined] %s\n", dirPath);
#endif
} else {
printf("Not link: %s (proceeding anyway)\n", dirPath);
//printf("Not link: %s (ignoring)\n", dirPath);
//continue;
}
if (fd > 2) {
//int fdFlags = fcntl(fd, F_GETFD);
int fdFlags = fcntl(fd, F_GETFL);
if (fdFlags == -1) {
perror("fcntl failed");
}
//off_t offset = lseek(fd, 0, SEEK_CUR);
off_t offset = 0;
if (offset == -1) {
perror("lseek failed");
}
if (arr != NULL) {
/*
arr[index] = (fileData *) malloc(sizeof (fileData));
arr[index]->flags = fdFlags;
arr[index]->offset = offset;
arr[index]->fd = fd;
strcpy(arr[index]->fdPath, realPath);*/
}
index++;
// ignore stdin, stdout, stderr
printf("Closing FD %d (flags %d, offset %zd)\n",
fd, fdFlags, offset);
close(fd);
}
}
}
closedir(d);
} else {
fprintf(stderr, "Could not open directory %s\n", path);
}
return index;
}
int main () {
deviceQ();
printf("=> Closing open file descriptors\n");
closeFileDescriptors (NULL);
deviceQ();
return 0;
}
最佳答案
你的期望是错误的。当您调用 dlclose(3) 时,只有“插件”(实际上是共享对象)被“关闭”(实际上,可能是 munmap
-ed),但不是资源(特别是它使用的文件描述符,可能还有堆分配的内存)。
此外,特别是在 Linux 上,dlclose
正在调用插件的所谓析构函数(那些用 __attribute__((destructor))
声明的函数,阅读 function attributes在 GCC 中)。
如果您正在编写一个共享库,您可以将其设计为在dlclose
时间释放一些 资源(通过析构函数运行适当的终结 函数)。一般来说,这不容易实现(并且应该是一个记录在案的约定)。
虚拟内存中的地址空间(由 mmap(2) 等获得)和文件描述符(由 open(2) 、 socket(2) 、 pipe(2) 等获得)等资源对于整个 process 是全局的(和公共(public)的)。因此,在一个共享库中获取一些资源(例如打开一些文件描述符)并在另一个共享库(或在主程序中)释放它是可能的(并且是合法的,如果有记录的话)。
由于资源“属于”整个过程,所以说释放图书馆获得的资源是没有意义的。
所以您的 closeFileDescriptors
很可能是一个巨大的错误(并且它可能泄漏了一些其他资源)。
(IIRC,OpenCL API 有一些方法来释放它的资源,例如设备、上下文、内核等....但我忘记了丑陋的细节;参见clReleaseContext
、clReleaseMemObject
等等,包括一些特定于实现的对象。)
阅读更多关于 garbage collection 的内容可能会拓宽您的思路。
另请阅读 Drepper 的论文:How To Write a Shared Library 和 credentials(7)
如果您绝对需要尽早释放 OpenCL 相关资源,更明智的方法可能是启动一个专用于 OpenCL 事物的不同子进程,并使用巧妙的 IPC 机制(例如 pipe(7) 、 shm_overview(7) 、 sem_overview(7) 等...)然后一旦您的 OpenCL 工作完成,就(正确地)终止该子进程。您利用了内核正在清除已失效进程使用的所有资源这一事实(不要忘记 wait
...它 - 例如使用 waitpid(2) - 以避免拥有 zombie processes )。如果您不熟悉所有内容,请先阅读 Advanced Linux Programming。
关于c - dlclose 不关闭库打开的文件句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30945894/
我在使用 MinGw 在 Windows 上构建 MLT 框架时遇到了一些问题。我尝试按照 http://www.mltframework.org/bin/view/MLT/WindowsBuild
场景是这样的: 我有一个应用程序 (main.exe),它使用 dlopen() 动态加载库 libA.so。 libA.so 依赖于另一个库 libB.so。 现在 libB.so 有一个构造函数,
我正在使用基本的 C 插件系统 dlclose()。这是我的代码: #include #include char** getPlugins() { int i; char** ta
我在 Linux 中遇到过以下问题。我有一些使用外部库的应用程序(应用程序未与其链接)。我通过 dlopen 打开库并使用其中的一些符号。当我尝试通过 dlclose 卸载库时出现问题,我仍然看到在
所以我正在研究共享库,我读到在进程终止时执行隐式 dlclose()。我想知道谁负责这个电话。例如,如果我写: #include int main() { printf("Hello
我正在制作一个简单的插件框架,我希望能够在其中 dlopen() 一个共享库(即插件),检查并使用提供的任何工厂函数,并最终 dlclose() 它,不留痕迹. 我的工厂系统很简单,只有一个导出函数返
我用 C 编写了一个用户空间应用程序,它使用插件库 plugin.so 与低级 Linux 内核驱动程序交互。我使用 dlopen() 打开 DLL。我有一个信号处理程序,它在收到 SIGINT 时调
我有一个使用 dlopen 加载的共享库(带有标志 RTLD_NOW | RTLD_GLOBAL )。如果这个库正在使用主程序中的函数,那么它不会卸载。所以我最终得到了这个共享库的相同代码,即使我卸载
我正在使用 dlopen 动态加载库,然后使用 dlclose 关闭它。我希望在 dlclose 完成后释放所有库资源,但在 dlclose 调用之后,库中仍有打开的文件描述符。我想知道如何确保在程序
plugin1.cpp: #include static class TestStatic { public: TestStatic() { std::cout #include
我的应用程序处理数千条消息并使用 dlopen/dlclose 等在运行时调用共享库中的函数。 我一直在分析运行时的内存,似乎(如我所料)dlclose() 在关闭后没有释放任何 malloc 的内存
我正在使用 dlopen() 和 dlclose() 加载和卸载模块。该模块包含一些需要在调用 dlclose() 时销毁的静态数据。然而,我发现在某些情况下,dlclose() 不会调用析构函数 -
我将在运行时加载共享库的依赖于操作系统的 API 包装在一个可移植的接口(interface)中。 问题是,在记录 close() 函数时,我注意到没有关于 dlclose() 或 FreeLibra
我正在从事一个跨平台项目,该项目由多个库组成,根据运行时条件动态地相互加载和卸载。目前我观察到一个崩溃,这似乎是由共享库之一中的静态对象在使用 dlclose() 卸载共享库之前被销毁这一事实引起的。
我有一个有趣的问题,我在互联网上的研究似乎没有解决。我正在尝试使用 dlfcn.h 中的函数在我的 C++ 项目中动态加载库。问题是当我尝试在运行时重新加载插件时(因为我对它们中的任何一个进行了更改)
在主程序中,我dlopen 和dlclose(分别为LoadLibrary 和FreeLibrary)一个共享库。共享库包含一个静态变量,该变量在 dlopen 时实例化,并在 dlclose 时销毁
在做了一些研究之后,我终于转向 SO 来问我的问题:在使用 malloc() 关闭库后,共享库(使用 new 或 dlclose() )动态分配的内存会发生什么情况| ?我观察到的行为是对此类内存的任
如果通过 dlopen 和 dlclose 机制使用共享库(或 DLL),并且如果创建的共享库有一些内存来自堆的全局变量,那么当 dlclose 时这些变量和内存会发生什么叫什么? 如果在同一个进程中
今天我正在寻找动态加载器内部深层魔法的一些启示。我正在为在 Linux 上运行的 C++ 应用程序调试/排除插件系统故障。它通过 dlopen (RTLD_NOW | RTLS_LOCAL) 加载插件
我的程序使用 dlopen 加载共享对象,然后使用 dlclose 卸载它。有时会再次加载此共享对象。我注意到静态变量没有重新初始化(这对我的程序很重要)所以我在 dlclose 之后添加了一个测试(
我是一名优秀的程序员,十分优秀!