Sejak versi 3.2 dari kernel. Anda dapat menggunakan panggilan sistem process_vm_readv untuk membaca memori proses tanpa gangguan.
ssize_t process_vm_readv(pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags);
Panggilan sistem ini mentransfer data antara ruang alamat dari proses pemanggilan ("proses lokal") dan proses yang diidentifikasi oleh pid ("proses jarak jauh"). Data bergerak langsung antara ruang alamat dari dua proses, tanpa melewati ruang kernel.
Untuk proses 1234 Anda bisa mendapatkan peta memorinya dengan membaca /proc/1234/maps
secara berurutan (file pseudo-tekstual) dan membaca memori virtual dengan mis. baca(2)-ing atau mmap(2)-ing segmen yang sesuai dari /proc/1234/mem
file pseudo-sparse.
Namun, saya yakin Anda tidak dapat menghindari semacam sinkronisasi (mungkin dengan ptrace(2), seperti gdb
tidak), karena proses 1234 dapat (dan memang) mengubah ruang alamatnya kapan saja (dengan mmap
&syscall terkait).
Situasinya berbeda jika proses yang dipantau 1234 tidak sewenang-wenang, tetapi jika Anda dapat memperbaikinya untuk berkomunikasi entah bagaimana dengan proses pemantauan.
Saya tidak yakin untuk mengerti mengapa Anda menanyakan hal ini. Dan gdb
dapat watch
beberapa lokasi tanpa menghentikan proses.
Jika Anda memiliki akses root dan menggunakan sistem linux, Anda dapat menggunakan skrip linux berikut (diadaptasi dari jawaban unix.stackexchange.com yang sangat baik dari Gilles dan jawaban awalnya diberikan dalam pertanyaan di atas tetapi termasuk SyntaxErrors dan bukan pythonic):
#!/usr/bin/env python
import re
import sys
def print_memory_of_pid(pid, only_writable=True):
"""
Run as root, take an integer PID and return the contents of memory to STDOUT
"""
memory_permissions = 'rw' if only_writable else 'r-'
sys.stderr.write("PID = %d" % pid)
with open("/proc/%d/maps" % pid, 'r') as maps_file:
with open("/proc/%d/mem" % pid, 'r', 0) as mem_file:
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r][-w])', line)
if m.group(3) == memory_permissions:
sys.stderr.write("\nOK : \n" + line+"\n")
start = int(m.group(1), 16)
if start > 0xFFFFFFFFFFFF:
continue
end = int(m.group(2), 16)
sys.stderr.write( "start = " + str(start) + "\n")
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
print chunk, # dump contents to standard output
else:
sys.stderr.write("\nPASS : \n" + line+"\n")
if __name__ == '__main__': # Execute this code when run from the commandline.
try:
assert len(sys.argv) == 2, "Provide exactly 1 PID (process ID)"
pid = int(sys.argv[1])
print_memory_of_pid(pid)
except (AssertionError, ValueError) as e:
print "Please provide 1 PID as a commandline argument."
print "You entered: %s" % ' '.join(sys.argv)
raise e
Jika Anda menyimpan ini sebagai write_mem.py, Anda dapat menjalankan ini (dengan python2.6 atau 2.7) atau di awal python2.5 (jika Anda menambahkan from __future__ import with_statement
) sebagai:
sudo python write_mem.py 1234 > pid1234_memory_dump
untuk membuang memori pid1234 ke file pid1234_memory_dump.