我想探索一个生命过程的记忆,当我这样做的时候,进程不能受到干扰-因此将gdb附加到进程(这将停止它)不是一个选项。因此,我希望从/proc/kcore获取此信息(如果你知道另一种方法,请让我知道)。所以我做了一个小实验。我创建了一个名为TEST的文件,里面只有“EXTRATESTEXTRA”。然后我用更少的钱打开了它
$ 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
所以我得出结论,这个字符串一定出现在0x 00624000和0x 00628000之间的某个地方,因此我将偏移量转换为十进制数,并使用dd从/proc/kcore获取内存:
$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1
令我惊讶的是,文件y.txt全是零(我没有在其中找到我要找的字符串)。
作为额外的惊喜,我同时用不同的测试文件运行了一个类似的测试,发现我正在使用的另一个测试字符串(两个进程同时运行)应该在相同的位置找到(转储和greping给出了相同的偏移量),所以一定有什么我不明白的地方。
- /proc/pid/maps不是应该显示内存的偏移量(即:如果它会说“XXX”在偏移0x 10,另一个程序不可能使用相同的偏移,我说得对吗?-这是我第二个惊喜的来源)
- 如何读取/proc/kmap以获取属于某个进程的内存,而该进程的pid我是知道的?
7条答案
按热度按时间svmlkihl1#
如果你有root访问权限,并且在linux系统上,你可以使用下面的linux脚本(改编自Gilles' excellent unix.stackexchange.com answer和上面问题中最初给出的答案,但包括SyntaxErrors,并且不是pythonic):
如果将其保存为write_mem.py,则可以运行此命令(使用python2.6或2.7)或在python2.5早期运行此命令(如果添加
from __future__ import with_statement
):将pid1234内存转储到文件pid1234_memory_dump。
eanckbw92#
对于进程1234,您可以通过顺序阅读
/proc/1234/maps
(文本伪文件)来获取其内存Map,并通过read(2)-ing或mmap(2)-ing/proc/1234/mem
稀疏伪文件的适当段来读取虚拟内存。但是,我相信您无法避免某种类型的同步(可能与ptrace(2)同步,就像
gdb
一样),因为进程1234可以(并且确实)随时更改其地址空间(使用mmap
和相关的系统调用)。如果被监视进程1234不是任意的,但是如果您可以改进它以某种方式与监视进程通信,则情况会有所不同。
我不太明白你为什么要问这个问题,而且
gdb
能够在不停止进程的情况下watch
一些位置。ugmeyewa3#
从3.2版本的内核开始,你可以使用process_vm_readv系统调用来读取进程内存,而不需要中断。
这些系统调用在调用进程(“本地进程”)和由pid标识的进程(“远程进程”)的地址空间之间传输数据。数据直接在两个进程的地址空间之间移动,而不经过内核空间。
klr1opcd4#
你必须使用
/proc/
pid/mem
来读取进程内存,我不推荐尝试读取/proc/kcore
或任何内核内存函数(这很耗时)。xhv8bpkk5#
如果您只想获取全局变量或指定地址的值,可以使用我的工具gvardump,而不是读取整个内存。gvardump将解析变量地址并很好地打印其值,而不会导致进程中断。
例如:
vtwuwzda6#
并且当我这样做时,进程不能受到干扰--因此将gdb附加到进程(这将停止它)不是一个选项。
我修改了gdb以避免附加。
使用this modified gdb,您可以运行
gdb -m <PID>
来探索内存,而无需停止进程。4xy9mtcn7#
我通过发出以下命令实现了这一点
[root@stage1 ~]# echo“PID [MySql]的内存使用情况:“;用于{私有、Rss、共享、交换、Pss}中的内存;执行grep $内存/进程/
ps aux |grep mysql |awk '{print $2}'|head -n 1
/smaps|awk -v存储器类型="$存储器”'{i=i+$2} END {打印存储器类型,“存储器使用:“i}' ;完成结果输出
PID [MySql]的内存使用量:
私有内存使用量:204
RSS内存使用量:1264
共享内存使用量:1060
交换内存使用量:0
Pss内存使用量:423