GNU/Linux >> Linux の 問題 >  >> Linux

生きているプロセスメモリを中断せずに読み取る

カーネルのバージョン 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 にダンプします。


Linux
  1. -bash:fork:メモリを割り当てられません

  2. bashでプロセスを強制終了せずにタイムアウト

  3. プロセスのピーク時のメモリ使用量

  1. Linux でメモリ使用量はどのように報告されますか?

  2. Unixで実行中のプロセスの環境変数?

  3. Linux プロセスのメモリをファイルにダンプする

  1. 手作業でコンテナを構築する:PID名前空間

  2. Linux –単一のLinuxプロセスのメモリ使用量を制限しますか?

  3. 開始したばかりのプロセスのpidを取得する方法