Reading living process memory without interrupting it

后端 未结 5 1228
独厮守ぢ
独厮守ぢ 2020-12-04 14:41

I would like to explore the memory of a living process, and when I do so, the process must not get disturbed - so attaching gdb to the process (which would stop it) is not a

相关标签:
5条回答
  • 2020-12-04 14:59

    For process 1234 you can get its memory map by reading sequentially /proc/1234/maps (a textual pseudo-file) and read the virtual memory by e.g. read(2)-ing or mmap(2)-ing appropriate segments of the /proc/1234/mem sparse pseudo-file.

    However, I believe you cannot avoid some kind of synchronization (perhaps with ptrace(2), as gdb does), since the process 1234 can (and does) alter its address space at any time (with mmap & related syscalls).

    The situation is different if the monitored process 1234 is not arbitrary, but if you could improve it to communicate somehow with the monitoring process.

    I'm not sure to understand why do you ask this. And gdb is able to watch some location without stopping the process.

    0 讨论(0)
  • 2020-12-04 15:00

    Since the 3.2 version of the kernel. You can use the process_vm_readv system call to read process memory without interruption.

    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);
    

    These system calls transfer data between the address space of the calling process ("the local process") and the process identified by pid ("the remote process"). The data moves directly between the address spaces of the two processes, without passing through kernel space.

    0 讨论(0)
  • 2020-12-04 15:06

    If you have root access and are on a linux system, you can use the following linux script (adapted from Gilles' excellent unix.stackexchange.com answer and the answer originally given in the question above but including SyntaxErrors and not being 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
    

    If you save this as write_mem.py, you can run this (with python2.6 or 2.7) or early in python2.5 (if you add from __future__ import with_statement) as:

    sudo python write_mem.py 1234 > pid1234_memory_dump
    

    to dump pid1234 memory to the file pid1234_memory_dump.

    0 讨论(0)
  • 2020-12-04 15:16

    i achieved this by issuing the below command

    [root@stage1 ~]# echo "Memory usage for PID [MySql]:"; for mem in {Private,Rss,Shared,Swap,Pss};do 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

    Result Output

    Memory usage for PID [MySql]:

    Private memory usage:204

    Rss memory usage:1264

    Shared memory usage:1060

    Swap memory usage:0

    Pss memory usage:423

    0 讨论(0)
  • 2020-12-04 15:18

    You'll have to use /proc/pid/mem to read process memory. I wouldn't recommend trying to read /proc/kcore or any of the kernel memory functions (which is time consuming).

    0 讨论(0)
提交回复
热议问题