正在读取 /proc/pid/mem 文件 returns 无

Reading /proc/pid/mem file returns nothing

我想通过读取/proc/pid/mem的内容并将其写入另一个文件来捕获当前进程到文件的内存映射。但是每次生成的文件都是空的。我使用sudo,所以我没有权限错误。当我将输入文件更改为某个测试文件时,如 "test_file_1.txt",一切都按预期工作。我做错了什么?

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char *argv[], char *envp[]) {
    char filename[100];

    pid_t pid = getpid();
    printf("pid: %i\n", pid);

////It works with an usual file
//  FILE *in_file = fopen("test_file_1.txt", "r");

////But doesn't work with this:
    sprintf(filename, "/proc/%i/mem", pid);
    FILE *in_file = fopen(filename, "r");
    if(!in_file){
        puts("in_file can't be opened");
    }

    sprintf(filename, "mem_%i.txt", pid);
    FILE *out_file = fopen(filename, "w");
    if(!out_file){
        puts("out_file can't be opened");
    }

    char line[500];
    while(fgets(line, 500, in_file)) {
        fputs(line, out_file);             
    }

    fclose(in_file);
    fclose(out_file);

    return 0;
}

尝试查看 /proc/pid/maps 以查看该文件是否包含您要查找的内存映射信息。

/proc/PID/mem 可以访问进程中映射的内存:访问此文件的第 N 字节等同于访问 (*unsigned char)<em>N</em> 在 C 中的进程内,或 ptrace(PTRACE_PEEKDATA, <em>PID </em>, (void*)<em>N</em>, NULL) 来自另一个进程(或 PTRACE_POKEDATA 用于写入,区别在于 ptrace 一次访问一个字,而不是一次访问一个字节)。

进程通常在地址 0 处没有任何映射。当您打开文件并开始读取时,您正在从地址 0 读取。由于那里没有任何内容,read 调用 returns EIO。使用 perror 获取有关 fgets.

失败的更多信息

请注意,fgets 不会让您从 /proc/PID/mem 读取,因为它包含二进制数据,但 fgets 仅适用于文本(不包含空字节的字符串) .使用 openlseekread 读取 /proc/PID/mem

在阅读 /proc/PID/mem 之前,您需要弄清楚进程将事物映射到何处。此信息在 /proc/PID/maps 中。该文件是一个文本文件,具有合理的行长度,因此使用 fopenfgets 是可以的。

如果您正在访问进程自己的内存,您可以使用 /proc/self/… 而不是内插 PID。

FILE *maps_file = fopen("/proc/self/maps", "r");
if (maps_file == NULL) {perror("/proc/self/maps"); exit(EXIT_FAILURE);}
char line[500];
while (fgets(line, sizeof(line), maps_file)) { ... }
fclose(maps_file);

而不是 proc/<pid>/mem,您应该使用 process_vm_readv(2)

真的。

/proc/<pid>/mem 是一个遗留接口,与 shell 中的 dd 一起使用仍然很可爱(“一切都是文件”,等等),但它没有意义从 C.

打扰它