我想探索一个活的过程的记忆,当我这样做时,过程一定不会受到干扰 – 所以将gdb附加到过程中(这会阻止它)不是一个选项。 因此,我想从/ proc / kcore得到这个信息(如果你知道另一种方法做到这一点,请让我知道)。 所以我做了一个小实验。 我创build了一个名为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
然后我使用这个脚本来创build所有文件的转储:
#!/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之间出现这个string。 因此,我将偏移量转换为十进制数,并使用dd从/ proc / kcore中获取内存:
$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1
令我惊讶的是,文件y.txt充满了零(我没有find我正在寻找的string)。
作为一个额外的惊喜,我用一个不同的testing文件同时运行了一个simmilartesting,发现我使用的另一个testingstring(两个进程同时运行)应该在同一个位置(倾销和greping给了相同的抵消)。 所以肯定有一些我不明白的东西。
是不是/ proc / pid / maps应该显示内存的偏移量(即:如果它会说“XXX”在偏移量0x10,另一个程序不能使用相同的偏移量我是吗? – 这是我的第二个惊喜的来源)
我如何读取/ proc / kmap来获取属于我知道的进程的内存?
总结答案并添加我自己的评论: – / proc / pid / maps显示内存的部分作为进程看到它(每个进程不同,在linux上search内存映射),所以不同的进程似乎是使用相同的内存部分(从他们的angular度来看)。 你可以从/ proc / pid / mem中以超级用户的身份(或像gdb这样的父进程使用ptrace来执行)读取这里指定的部分 – /proc/kcore
中的内存与进程的内存不一样/proc/pid/mem
– 要在/proc/kcore
search进程的内存,人们必须弄清楚进程的内存是如何映射到内核内存的(很多杂乱的东西和耗时)。所以要获得进程内存,首先读取/proc/pid/maps
中允许读/写的区域,然后从/proc/pid/mem
转储复制区域。 下面的脚本转储所有可写区域(来源: https : //unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux )。 编辑:修改后的工作python脚本被移动到自己的答案,所以它可以注意不同的问题。
对于进程1234,您可以通过顺序读取/proc/1234/maps
(一个文本伪文件)并通过读取(2) -ing或mmap(2)读取虚拟内存来获得它的内存映射。 /proc/1234/mem
稀疏伪文件。
但是,我相信你不能避免某种同步(可能跟gdb
一样使用ptrace(2) ),因为进程1234可以(并且随时)改变其地址空间(使用mmap
&related syscalls)。
如果被监控进程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.5(如果from __future__ import with_statement
添加)运行此操作(使用python2.6或2.7)或早于以下情况:
sudo python write_mem.py 1234 > pid1234_memory_dump
将pid1234内存转储到文件pid1234_memory_dump。
您将不得不使用/ proc / mem来读取进程内存,我不建议尝试读取/ proc / kcore或任何内核内存函数(这是耗时的)
我通过发出下面的命令来实现这一点
[root @ stage1〜]#echo“PID的内存使用量[MySql]:”; 在mem {private,Rss,Shared,Swap,Pss}; grep $ mem / proc / ps aux |grep mysql |awk '{print $2}'|head -n 1
/ smaps | awk -v mem_type =“$ mem”'{i = i + $ 2} END {print mem_type,“memory usage:”i}“; done
结果输出
PID的内存使用情况[MySql]:
私有内存使用情况:204
Rss内存使用情况:1264
共享内存使用情况:1060
交换内存使用情况:0
Pss内存使用情况:423