コード例 #1
0
def parse_smaps_memory_region(pid, lines, has_header=True):
    """Parse a whole smaps region, which may look like:

7f5c8550e000-7f5c85554000 r--p 00000000 08:06 1309629   /fonts/Arial_Bold.ttf
Size:                280 kB
Rss:                 152 kB
Pss:                  86 kB
Shared_Clean:        132 kB
Shared_Dirty:         12 kB
Private_Clean:        20 kB
Private_Dirty:         1 kB
Referenced:          152 kB
Anonymous:             2 kB
AnonHugePages:         3 kB
Shared_Hugetlb:        4 kB
Private_Hugetlb:       5 kB
Swap:                  6 kB
SwapPss:               7 kB
KernelPageSize:        8 kB
MMUPageSize:           9 kB
Locked:               10 kB
VmFlags: rd mr mw me sd"""

    has_header = is_memory_region_header(lines[0])

    if has_header:
        region = parse_smaps_header(lines[0])
        if region.name == '[vsyscall]':
            return None
        lines = lines[1:]
    else:
        region = MemoryRegion(free=False)

    region.pid = pid

    global _smaps_string_mappings
    for line in lines:
        LOGGER.debug('Parsing line: %s' % line)
        parts = re.split('[ :]+', line.strip())
        if len(parts) < 2:
            LOGGER.debug('Skipping smaps line that is too short: %s' % line)
        elif 'Size' == parts[0]:
            # We calculate the size from the address ranges instead.
            pass
        elif 'VmFlags' == parts[0]:
            region.vm_flags = parts[1:]
        else:
            # All other lines should be an amount of some type of memory.
            try:
                region.__dict__[_smaps_string_mappings[parts[0]]] = int(
                    parts[1]) * 1024
            except KeyError:
                LOGGER.warn("Line not recognised: '%s'" % line)
    return region
コード例 #2
0
def read_tailed_files(stream):
    section_name = ''
    data = ''
    processes = ProcessList()
    current_process = None
    current_thread = None
    out = {}
    out['stats'] = SystemStats()
    out['meminfo'] = MemoryStats()

    for line in stream:
        LOGGER.debug('Got line: %s' % line)
        if line == '':
            continue
        # tail gives us lines like:
        #
        #     ==> /proc/99/smaps <==
        #
        # between files
        elif line.startswith('==>'):
            _parse_section(section_name, current_process, current_thread, data,
                           out)
            data = ''
            section_name = ''
            current_process = None
            current_thread = None

            if '/proc/loadavg' in line:
                section_name = 'loadavg'
                continue
            elif '/proc/uptime' in line:
                section_name = 'uptime'
                continue
            elif '/proc/vmstat' in line:
                section_name = 'vmstat'
                continue
            elif '/proc/net/stat' in line:
                # We don't care about this entry. Skip it.
                continue

            # Now parse the new line.
            match = re.match(r'==> /proc/([0-9]+)/([\w]+) <==', line)
            if match is None:
                if any(x in line for x in
                       ['/proc/stat', '/proc/self/', '/proc/thread-self/']):
                    # We just ignore these entries, interetesting as they are,
                    # for now.
                    pass
                elif '/proc/meminfo' in line:
                    section_name = 'meminfo'
                else:
                    match = re.match(
                        r'==> /proc/([0-9]+)/task/([0-9]+)/stat <==', line)
                    if match is None:
                        # The line might not be parsed here. There are a few
                        LOGGER.warn('Unrecognised line, skipping: %s' % line)
                    else:
                        section_name = 'stat'
                        pid = int(match.group(1))  # process id
                        tid = int(match.group(2))  # thread id
                        current_thread = processes.get(pid).get_thread(tid)
            else:
                section_name = match.group(2)
                current_process = processes.get(pid=int(match.group(1)))

        elif current_process and section_name == 'smaps' and is_memory_region_header(
                line):
            # We get here on reaching a new memory region in a smaps file.
            _save_smaps_region(current_process.maps, out['meminfo'],
                               current_process.pid, data)
            data = line
        elif section_name != '':
            data += "\n" + line
        else:
            LOGGER.debug('Skipping line: %s' % line)

    # We've hit the end, parse the section we were in.
    _parse_section(section_name, current_process, current_thread, data, out)

    return out['stats'], processes, out['meminfo']