Linux环境下C语言实现:获取关联/dev/yoyo内核模块的进程内存映射地址与打开文件描述符
好问题!在Linux环境下,完全可以用纯C代码实现你要的功能,不需要依赖Shell管道或者popen这类调用——毕竟/proc文件系统本身就是内核给用户态程序提供的进程信息接口,我们直接操作它就行。下面分两部分详细讲,顺便聊聊有没有原生系统调用能直接干这个事儿。
获取已打开的/dev/yoyo文件描述符
Linux的/proc/self/fd目录下的每个条目,都是当前进程打开的文件描述符对应的符号链接,链接目标就是该fd指向的文件/设备路径。我们只需要遍历这个目录,读取每个链接的目标路径,就能筛选出指向/dev/yoyo的fd。
示例代码:
#include <stdio.h> #include <dirent.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define TARGET_DEV "/dev/yoyo" void find_yoyo_fds() { // 打开/proc/self/fd目录 DIR *dir = opendir("/proc/self/fd"); if (!dir) { perror("Failed to open /proc/self/fd"); return; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { // 跳过.和..这两个特殊目录项 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } // 构建符号链接的完整路径 char link_path[256]; snprintf(link_path, sizeof(link_path), "/proc/self/fd/%s", entry->d_name); // 读取符号链接的目标路径 char target_path[256]; ssize_t len = readlink(link_path, target_path, sizeof(target_path)-1); if (len == -1) { perror("Failed to read symlink"); continue; } target_path[len] = '\0'; // 确保字符串以'\0'结尾 // 匹配目标设备路径 if (strcmp(target_path, TARGET_DEV) == 0) { printf("Found matching FD: %s\n", entry->d_name); } } closedir(dir); }
获取/dev/yoyo对应的内存映射地址
/proc/self/maps文件记录了当前进程所有内存区域的映射信息,每一行对应一个内存段,末尾会标注该段映射的文件/设备路径。我们可以直接打开这个文件,逐行读取并筛选包含/dev/yoyo的行。
示例代码:
#include <stdio.h> #include <string.h> #define TARGET_DEV "/dev/yoyo" void find_yoyo_maps() { // 打开/proc/self/maps文件 FILE *maps_file = fopen("/proc/self/maps", "r"); if (!maps_file) { perror("Failed to open /proc/self/maps"); return; } char line[1024]; while (fgets(line, sizeof(line), maps_file) != NULL) { // 检查当前行是否包含目标设备路径 if (strstr(line, TARGET_DEV) != NULL) { printf("Found matching memory map:\n%s", line); // line本身已包含换行符 } } fclose(maps_file); }
有没有原生函数可以直接获取?
遗憾的是,Linux内核并没有提供直接返回特定设备对应的文件描述符或内存映射的原生系统调用。这类信息属于进程的私有状态(文件描述符表、虚拟地址空间),内核通过/proc文件系统将这些信息标准化地暴露给用户态,所以读取/proc下的对应文件是官方推荐的、标准的做法。
完整整合示例
把上面两个函数整合到一起,就能得到一个完整的工具:
#include <stdio.h> #include <dirent.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define TARGET_DEV "/dev/yoyo" void find_yoyo_fds() { DIR *dir = opendir("/proc/self/fd"); if (!dir) { perror("Failed to open /proc/self/fd"); return; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } char link_path[256]; snprintf(link_path, sizeof(link_path), "/proc/self/fd/%s", entry->d_name); char target_path[256]; ssize_t len = readlink(link_path, target_path, sizeof(target_path)-1); if (len == -1) { perror("Failed to read symlink"); continue; } target_path[len] = '\0'; if (strcmp(target_path, TARGET_DEV) == 0) { printf("Matching FD: %s\n", entry->d_name); } } closedir(dir); } void find_yoyo_maps() { FILE *maps_file = fopen("/proc/self/maps", "r"); if (!maps_file) { perror("Failed to open /proc/self/maps"); return; } char line[1024]; while (fgets(line, sizeof(line), maps_file) != NULL) { if (strstr(line, TARGET_DEV) != NULL) { printf("Matching memory map:\n%s", line); } } fclose(maps_file); } int main() { printf("Searching for /dev/yoyo file descriptors...\n"); find_yoyo_fds(); printf("\nSearching for /dev/yoyo memory maps...\n"); find_yoyo_maps(); return 0; }
编译运行方式:
gcc -o yoyo_check yoyo_check.c ./yoyo_check
内容的提问来源于stack exchange,提问作者yfr24493AzzrggAcom
相关产品推荐
相关产品推荐

