正在读取 /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
仅适用于文本(不包含空字节的字符串) .使用 open
、lseek
和 read
读取 /proc/PID/mem
。
在阅读 /proc/PID/mem
之前,您需要弄清楚进程将事物映射到何处。此信息在 /proc/PID/maps
中。该文件是一个文本文件,具有合理的行长度,因此使用 fopen
和 fgets
是可以的。
如果您正在访问进程自己的内存,您可以使用 /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.
打扰它
我想通过读取/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
仅适用于文本(不包含空字节的字符串) .使用 open
、lseek
和 read
读取 /proc/PID/mem
。
在阅读 /proc/PID/mem
之前,您需要弄清楚进程将事物映射到何处。此信息在 /proc/PID/maps
中。该文件是一个文本文件,具有合理的行长度,因此使用 fopen
和 fgets
是可以的。
如果您正在访问进程自己的内存,您可以使用 /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.