カーネルのバージョン 3.2 以降。 process_vm_readv システム コールを使用して、中断することなくプロセス メモリを読み取ることができます。
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);
これらのシステム コールは、呼び出しプロセス (「ローカル プロセス」) のアドレス空間と pid で識別されるプロセス (「リモート プロセス」) の間でデータを転送します。データは、カーネル空間を通過せずに、2 つのプロセスのアドレス空間の間を直接移動します。
プロセス 1234 の場合、/proc/1234/maps
を順番に読み取ることで、そのメモリ マップを取得できます。 (テキストの疑似ファイル)、たとえば次の方法で仮想メモリを読み取ります。 /proc/1234/mem
の適切なセグメントを read(2) または mmap(2) する スパース疑似ファイル。
ただし、ある種の同期を回避することはできないと思います (おそらく、gdb
のように ptrace(2) を使用) プロセスはいつでもそのアドレス空間を変更できる (実際に変更する) ため (mmap
を使用) &関連するシステムコール)
監視対象プロセス 1234 が恣意的でない場合、状況は異なりますが、監視プロセスと何らかの形で通信するように改善できる場合.
なぜあなたがこれを尋ねるのか理解できません。そして gdb
watch
できる プロセスを停止することなく、どこかの場所で。
root アクセス権があり、Linux システムを使用している場合は、次の Linux スクリプトを使用できます (Gilles の優れた unix.stackexchange.com の回答と、上記の質問で最初に与えられたが、SyntaxErrors を含み、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
これを write_mem.py として保存すると、これを (python2.6 または 2.7 で) または python2.5 の早い段階で (from __future__ import with_statement
を追加した場合) 実行できます。 ) として:
sudo python write_mem.py 1234 > pid1234_memory_dump
pid1234 メモリをファイル pid1234_memory_dump にダンプします。