如何找到用到某个动态库的所有进程
要查找使用特定动态库(共享库)的所有进程,可以通过以下方法在 Linux 系统中实现:
方法 1:使用 lsof
命令(推荐) 1 sudo lsof /path/to/library.so
说明 :
替换 /path/to/library.so
为动态库的完整路径 (如 /usr/lib/libcrypto.so.1.1
)。
输出包含使用该库的进程 ID(PID)、进程名等信息。
示例:1 sudo lsof /usr/lib/libc.so.6
方法 2:扫描 /proc
文件系统 通过脚本遍历所有进程的映射文件:
1 2 3 4 5 6 7 #!/bin/bash library_name="目标库名" for pid in $(ps -e -o pid | tail -n +2); do if grep -q "$library_name " /proc/$pid /maps 2>/dev/null; then echo "PID $pid : $(cat /proc/$pid/comm) " fi done
说明 :
将 目标库名
替换为库的名称(如 libssl.so.3
)。
脚本会输出所有加载该库的进程 PID 和名称。
需要 sudo
权限查看其他用户的进程。
方法 3:使用 fuser
命令 1 sudo fuser -v /path/to/library.so
说明 :
输出显示使用该文件的进程及用户信息。
需要库的完整路径 。
方法 4:组合命令(快速查找) 1 pgrep -f "$(realpath /path/to/library.so) " | xargs ps -p
说明 :
realpath
解析库的绝对路径。
pgrep
匹配路径,ps
显示进程详情。
常见问题解决
找不到库路径 :
使用 ldconfig -p | grep 库名
查找库的完整路径:1 ldconfig -p | grep libssl
权限不足 :
库被多个进程使用 :
结合 pstree
查看父子进程关系:1 sudo lsof /path/to/library.so | awk '{print $2}' | xargs pstree -p
示例输出 1 2 3 4 $ sudo lsof /usr/lib/libc.so.6 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 1234 root mem REG 8,1 2029224 123456 /usr/lib/libc.so.6 python 5678 user mem REG 8,1 2029224 123456 /usr/lib/libc.so.6
通过以上方法,可快速定位使用特定动态库的进程。推荐优先使用 lsof
或 fuser
命令。
是否有c函数接口支持
在 Linux 系统中,没有直接的标准 C 库函数可以查询使用特定动态库的所有进程。但可以通过以下方法间接实现类似功能:
1. 使用 /proc
文件系统(推荐) 这是最接近 C 接口的解决方案,通过读取 /proc
文件系统获取信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <stdio.h> #include <dirent.h> #include <string.h> #include <ctype.h> int main (int argc, char *argv[]) { if (argc != 2 ) { fprintf (stderr , "Usage: %s <library_name>\n" , argv[0 ]); return 1 ; } const char *target_lib = argv[1 ]; DIR *proc_dir = opendir("/proc" ); if (!proc_dir) { perror("opendir" ); return 1 ; } struct dirent *entry ; while ((entry = readdir(proc_dir))) { if (entry->d_type != DT_DIR) continue ; char *endptr; long pid = strtol(entry->d_name, &endptr, 10 ); if (*endptr != '\0' ) continue ; char maps_path[256 ]; snprintf (maps_path, sizeof (maps_path), "/proc/%s/maps" , entry->d_name); FILE *maps_file = fopen(maps_path, "r" ); if (!maps_file) continue ; char line[1024 ]; int found = 0 ; while (fgets(line, sizeof (line), maps_file)) { if (strstr (line, target_lib)) { found = 1 ; break ; } } fclose(maps_file); if (found) { char comm_path[256 ]; char comm[256 ] = "unknown" ; snprintf (comm_path, sizeof (comm_path), "/proc/%s/comm" , entry->d_name); FILE *comm_file = fopen(comm_path, "r" ); if (comm_file) { fgets(comm, sizeof (comm), comm_file); comm[strcspn (comm, "\n" )] = 0 ; fclose(comm_file); } printf ("PID: %s, Name: %s\n" , entry->d_name, comm); } } closedir(proc_dir); return 0 ; }
编译运行:
1 2 gcc find_lib_users.c -o find_lib_users sudo ./find_lib_users libc.so.6
2. 使用 libproc
库(更高级) 部分 Linux 发行版提供 libproc
库(在 libprocps-dev
或类似包中):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <proc/readproc.h> void find_processes_using_lib (const char *libname) { PROCTAB *proc = openproc(PROC_FILLCOM | PROC_FILLSTAT); proc_t *proc_info; while ((proc_info = readproc(proc, NULL ))) { if (proc_info->cmdline) { for (int i = 0 ; proc_info->cmdline[i]; i++) { if (strstr (proc_info->cmdline[i], libname)) { printf ("PID: %d, Name: %s\n" , proc_info->tid, proc_info->cmd); break ; } } } freeproc(proc_info); } closeproc(proc); }
3. 系统调用组合 虽然没有单一的系统调用,但可以组合使用:
1 2 3 4 5 6 7 8 9 10 11 12 #include <sys/syscall.h> FILE *pids = popen("ps -e -o pid=" , "r" ); while (fgets(line, sizeof (line), pids)) { pid_t pid = atoi(line); char maps_path[50 ]; sprintf (maps_path, "/proc/%d/maps" , pid); }
注意事项
需要 root 权限 :查看其他用户的进程需要特权
进程瞬态性 :进程可能在扫描过程中退出
路径匹配 :
使用库的完整路径更准确(如 /usr/lib/libc.so.6
)
部分匹配可能误报(如 libssl.so
可能匹配 libssl.so.1.1
)
效率 :扫描所有进程在大型系统上可能有性能影响
虽然标准 C 库没有直接提供此功能,但通过 /proc
文件系统可以可靠地实现该功能,这也是大多数系统工具(如 lsof
、fuser
)的内部实现方式。