Od verze 3.2 jádra. Systémové volání process_vm_readv můžete použít ke čtení paměti procesu bez přerušení.
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);
Tato systémová volání přenášejí data mezi adresním prostorem volajícího procesu ("místní proces") a procesem identifikovaným bypid ("vzdálený proces"). Data se přesouvají přímo mezi adresními prostory dvou procesů, aniž by procházela prostorem jádra.
Pro proces 1234 můžete získat jeho paměťovou mapu postupným čtením /proc/1234/maps
(textový pseudosoubor) a číst virtuální paměť např. read(2)-ing nebo mmap(2)-ing příslušných segmentů /proc/1234/mem
řídký pseudosoubor.
Věřím však, že se nějakému druhu synchronizace nevyhnete (možná s ptrace(2), jako gdb
dělá), protože proces 1234 může (a dělá) kdykoli změnit svůj adresní prostor (pomocí mmap
a související systémová volání).
Situace je jiná, pokud monitorovaný proces 1234 není libovolný, ale pokud jej můžete vylepšit, aby nějak komunikoval s procesem monitorování.
Nejsem si jistý, že rozumím, proč se na to ptáte. A gdb
je schopen watch
nějaké místo bez zastavení procesu.
Pokud máte přístup root a používáte linuxový systém, můžete použít následující linuxový skript (upravený z vynikající Gillesovy odpovědi unix.stackexchange.com a odpovědi původně uvedené ve výše uvedené otázce, ale včetně SyntaxErrors a bez 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
Pokud to uložíte jako write_mem.py, můžete to spustit (s python2.6 nebo 2.7) nebo brzy v python2.5 (pokud přidáte from __future__ import with_statement
) jako:
sudo python write_mem.py 1234 > pid1234_memory_dump
pro výpis paměti pid1234 do souboru pid1234_memory_dump.