linux - 在不中断的情况下读取生活过程内存

标签 linux memory

我想探索一个活进程的内存,当我这样做时,进程不能受到干扰 - 所以将 gdb 附加到进程(这会停止它)不是一种选择。 因此,我想从/proc/kcore 获取此信息(如果您知道另一种方法,请告诉我)。 所以我做了一个小实验。我创建了一个名为 TEST 的文件,里面只有“EXTRATESTEXTRA”。 然后我用less打开它

$ less TEST

我得到了这个进程的PID

$ ps aux | grep TEST
user    7785  0.0  0.0  17944   992 pts/8    S+   16:15   0:00 less TEST
user    7798  0.0  0.0  13584   904 pts/9    S+   16:16   0:00 grep TEST

然后我使用这个脚本创建了所有文件的转储:

#!/bin/bash
grep rw-p /proc/$1/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done

(我在这个网站上找到它https://serverfault.com/questions/173999/dump-a-linux-processs-memory-to-file)

$ sudo ./dump_all_pid_memory.sh 7785

之后,我在所有转储文件中查找“TRATESTEX”:

$ grep -a -o -e '...TRATESTEX...' ./*.dump
./7785-00624000-00628000.dump:HEXTRATESTEXTRA
./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA
./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA

所以我得出结论,这个字符串一定在 0x00624000 和 0x00628000 之间出现。 因此,我将偏移量转换为十进制数并使用 dd 从/proc/kcore 获取内存:

$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1

令我惊讶的是,文件 y.txt 中全是零(我没有在其中找到我要查找的字符串)。

作为一个额外的惊喜,我同时用不同的测试文件运行了一个类似的测试,发现我正在使用的另一个测试字符串 (同时运行较少的两个进程)应该在同一个位置找到(转储和 greping 给出了相同的偏移量)。 所以肯定有什么我没看清楚的地方。

  • /proc/pid/maps 不是应该显示内存的偏移量吗(即:如果它说“XXX”位于偏移量 0x10,那么另一个程序不能使用相同的偏移量吗?对吧?-这是我第二个惊喜的来源)

  • 如何读取/proc/kmap 以获取属于我知道的 pid 进程的内存?

最佳答案

如果您有 root 访问权限并且在 linux 系统上,您可以使用以下 linux 脚本(改编自 Gilles' excellent unix.stackexchange.com answer 以及上面问题中最初给出的答案,但包括 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 - 在不中断的情况下读取生活过程内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12977179/

相关文章:

string - Delphi 应用程序泄漏 AnsiStrings

java - 如何使用外部类路径执行可运行的 jar?

linux - 执行选项 : what is zeroth argument to command?

linux - 从多个文件中逐行删除特定行

c - shmat() 返回的虚拟内存地址指向不同的硬件内存位置

java - native 内存与 Java 应用程序内存

memory - 如何使用页表将虚拟地址转换为物理地址?

linux - 搜索并终止进程,并在 bash 脚本上启动新进程

python - 使用 Python 向远程进程发送信号

c++ - 如何加载自定义字体以便我可以在 DirectX 中使用它们?