简体   繁体   English

读取 /proc/pid/mem 文件不返回任何内容

[英]Reading /proc/pid/mem file returns nothing

I want to catch the memory mapping of current process to a file by reading the content of /proc/pid/mem and writing it to another file.我想通过读取/proc/pid/mem并将其写入另一个文件来捕获当前进程到文件的内存映射。 But the resulting file is empty every time.但是每次生成的文件都是空的。 I use sudo , so I have no permission errors.我使用sudo ,所以我没有权限错误。 When I change the input file to some testing file, like "test_file_1.txt" , all works as expected.当我将输入文件更改为某个测试文件时,例如"test_file_1.txt" ,一切都按预期工作。 What I do wrong?我做错了什么?

#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;
}

Instead of proc/<pid>/mem , you should use process_vm_readv(2) .您应该使用process_vm_readv(2)而不是proc/<pid>/mem

Really.真的。

/proc/<pid>/mem is a legacy interface, which is still cute to use with dd from the shell ("everything is a file", etc), but it makes no point to bother with it from C. /proc/<pid>/mem是一个遗留接口,它在 shell 中与dd一起使用仍然很可爱(“一切都是文件”等),但是从 C 中打扰它没有意义。

/proc/PID/mem gives access to the memory of the process as it is mapped in the process: accessing the N th byte of this file is equivalent to accessing (*unsigned char) N inside the process in C, or ptrace(PTRACE_PEEKDATA, PID , (void*) N , NULL) from another process (or PTRACE_POKEDATA for writing, and with the difference that ptrace accesses one word at a time, not one byte at a time). /proc/PID/mem允许访问在进程中映射的进程的内存:访问此文件的第N个字节相当于在 C 中访问进程内的(*unsigned char) N ,或ptrace(PTRACE_PEEKDATA, PID , (void*) N , NULL)来自另一个进程(或PTRACE_POKEDATA用于写入,区别在于ptrace访问一个单词,而不是一次访问一个字节)。

Processes usually have nothing mapped at address 0. When you open the file and start reading, you're reading from address 0. Since there's nothing there, the read call returns EIO .进程通常在地址 0 没有任何映射。当您打开文件并开始读取时,您正在从地址 0 读取。由于那里没有任何内容,因此read调用返回EIO Use perror to get more information about the failure of fgets .使用perror获取有关fgets失败的更多信息。

Note that fgets won't let you read from /proc/PID/mem because it contains binary data, but fgets only works on text (strings that don't contain null bytes).请注意, fgets不会让您从/proc/PID/mem读取,因为它包含二进制数据,但fgets仅适用于文本(不包含空字节的字符串)。 Use open , lseek and read to read from /proc/PID/mem .使用openlseekread/proc/PID/mem读取。

Before reading from /proc/PID/mem , you need to figure out where the process has things mapped.在从/proc/PID/mem读取之前,您需要弄清楚进程的映射位置。 This information is in /proc/PID/maps .此信息位于/proc/PID/maps This file is in a text file with reasonable line lengths, so using fopen and fgets is fine.此文件位于具有合理fopen的文本文件中,因此使用fopenfgets

If you're accessing the process's own memory, you can use /proc/self/… instead of interpolating the PID.如果您正在访问进程自己的内存,则可以使用/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/maps以查看该文件是否具有您要查找的内存映射信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM