Reputation: 1093
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. But the resulting file is empty every time. I use sudo
, so I have no permission errors. When I change the input file to some testing file, like "test_file_1.txt"
, all works as expected. 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;
}
Upvotes: 2
Views: 4215
Reputation:
Instead of proc/<pid>/mem
, you should use process_vm_readv(2)
.
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.
Upvotes: 3
Reputation: 107759
/proc/PID/mem
gives access to the memory of the process as it is mapped in the process: accessing the Nth 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).
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
. Use perror
to get more information about the failure of 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). Use open
, lseek
and read
to read from /proc/PID/mem
.
Before reading from /proc/PID/mem
, you need to figure out where the process has things mapped. This information is in /proc/PID/maps
. This file is in a text file with reasonable line lengths, so using fopen
and fgets
is fine.
If you're accessing the process's own memory, you can use /proc/self/…
instead of interpolating the 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);
Upvotes: 3
Reputation: 84
Try looking at /proc/pid/maps
to see if that file has the memory mapping info you are looking for.
Upvotes: 1