Linux内存检测工具memeleak

memleak

功能

memleak是一个BCC工具,它跟踪内存分配和空闲事件以及分配堆栈跟踪,随着时间的推移可以显示长期幸存者:那些没有被释放的分配。

示例

例如,在bash shell进程中运行memleak

memleak -p 3126

Attaching to pid 3228, Ctrl+C to quit.
[09:14:15] Top 10 stacks with outstanding 
allocations:
[...]
       960 bytes in 1 allocations from stack
              xrealloc+0x2a [bash]
              strvec_resize+0x2b [bash]
              maybe_make_export_env+0xa8 [bash]
              execute_simple_command+0x269 [bash]
              execute_command_internal+0x862 [bash]
              execute_connection+0x109 [bash]
              execute_command_internal+0xc18 [bash]
              execute_command+0x6b [bash]
              reader_loop+0x286 [bash]
              main+0x969 [bash]
              libc_start_main+0xe7 [libc-2.27.so]
              [unknown]
       1473 bytes in 51 allocations from stack
              xmalloc+0x18 [bash]
              make_env_array_from_var_list+0xc8 
[bash]
              make_var_export_array+0x3d [bash]
              maybe_make_export_env+0x12b [bash]
              execute_simple_command+0x269 [bash]
              execute_command_internal+0x862 [bash]
              execute_connection+0x109 [bash]
              execute_command_internal+0xc18 [bash]
              execute_command+0x6b [bash]
              reader_loop+0x286 [bash]
              main+0x969 [bash]
              libc_start_main+0xe7 [libc-2.27.so]
              [unknown]
[...]

默认情况下,它每5秒打印一次输出,显示分配堆栈和尚未释放的字节总数。最后一个堆栈显示,通过execute_command()和make_env_array_from_var_list()分配了1473个字节。
如果不提供-p PID, memleak 将跟踪内核分配:

memleak

Attaching to kernel allocators, Ctrl+C to quit.
[...]
[09:19:30] Top 10 stacks with outstanding 
allocations:
[...]
       15384576 bytes in 3756 allocations from 
stack
              alloc_pages_nodemask+0x209 [kernel]
              alloc_pages_vma+0x88 [kernel]
              handle_pte_fault+0x3bf [kernel]
              handle_mm_fault+0x478 [kernel]
              handle_mm_fault+0xb1 [kernel]
              __do_page_fault+0x250 [kernel]
              do_page_fault+0x2e [kernel]
               page_fault+0x45 [kernel]
[...]

对于进程目标,memleak通过跟踪用户级分配函数来工作:malloc()、calloc()、free()等。对于内核,它使用kmem跟踪点:kmem:kmalloc、kmem:kfree等。命令行用法:

memleak [options] [-p PID] [-c COMMAND] [interval[count]]

Options include:
• -s RATE: sample one in every RATE allocations to lower
在每个比率分配中抽取一个样本以降低管理费用
• -o OLDER: prune allocations younger than OLDER in milliseconds.
以毫秒为单位删除更早期的分配
目前,这意味着memleak更多地是一个故障排除或调试工具,而不是日常的生产分析工具,直到uprobes的性能得到极大改善。

代码

#!/usr/bin/python
#

memleak   Trace and display outstanding allocations to detect

memory leaks in user-mode processes and the kernel.

#

USAGE: memleak [-h] [-p PID] [-t] [-a] [-o OLDER] [-c COMMAND]

[--combined-only] [--wa-missing-free] [-s SAMPLE_RATE]

[-T TOP] [-z MIN_SIZE] [-Z MAX_SIZE] [-O OBJ]

[interval] [count]

#

Licensed under the Apache License, Version 2.0 (the "License")

Copyright (C) 2016 Sasha Goldshtein.

//python引入的模块和包
from bcc import BPF
from time import sleep
from datetime import datetime
import resource
import argparse
import subprocess
import os
import sys

class Allocation(object):
    def init(self, stack, size):
        //定义init函数,self代表自身,
        self.stack = stack
        self.count = 1
        self.size = size

def update(self, size):
    self.count += 1
    self.size += size

def run_command_get_output(command):
        p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        //commadn.split命令,stdout值是PIPE,则表示需要创建一个新的管道,stderr值是STDOUT,表示子进程的标准错误也输出到标准输出。
        //split命令可以将一个大文件分割成很多个小文件,有时需要将文件分割成更小的片段,比如为提高可读性,生成日志等。
        return iter(p.stdout.readline, b'')
        //iter() 函数用来生成迭代器。
def run_command_get_pid(command):
        p = subprocess.Popen(command.split())
        return p.pid
        //返回进程p的pid

examples = """

EXAMPLES:
./memleak -p $(pidof allocs)
        Trace allocations and display a summary of "leaked" (outstanding)
        allocations every 5 seconds
        跟踪分配,并每5秒显示“泄漏”(未完成)分配的摘要
./memleak -p $(pidof allocs) -t
        Trace allocations and display each individual allocator function call
        跟踪分配并显示每个单独的分配器函数调用
./memleak -ap $(pidof allocs) 10
        Trace allocations and display allocated addresses, sizes, and stacks
        every 10 seconds for outstanding allocations
        跟踪分配,并每10秒显示未完成分配的地址、大小和堆栈
./memleak -c "./allocs"
        Run the specified command and trace its allocations
        运行指定的命令并跟踪其分配
./memleak
        Trace allocations in kernel mode and display a summary of outstanding
        allocations every 5 seconds
        跟踪内核模式下的分配,并每5秒显示未完成分配的摘要
./memleak -o 60000
        Trace allocations in kernel mode and display a summary of outstanding
        allocations that are at least one minute (60 seconds) old
            跟踪内核模式下的分配,并显示至少一分钟(60)以前的未完成分配的摘要
./memleak -s 5
        Trace roughly every 5th allocation, to reduce overhead
        大约每5次跟踪一次,以减少开销
"""

description = """
Trace outstanding memory allocations that weren't freed.
Supports both user-mode allocations made with libc functions and kernel-mode
allocations made with kmalloc/kmem_cache_alloc/get_free_pages and corresponding
memory release functions.
功能描述:跟踪未释放的未完成的内存分配。支持使用libc函数和内核模式进行的用户模式分配
使用kmalloc / kmem_cache_alloc / get_free_pages和相应的分配内存释放功能。
"""

parser = argparse.ArgumentParser(description=description,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=examples)
"""
parser模块为Python的内部解析器和字节码编译器提供了一个接口。该接口的主要目的是
允许Python代码编辑Python表达式的分析树并从中创建可执行代码。这比试图将任意Python代码
片段解析并修改为字符串更好,因为解析是以与形成应用程序的代码相同的方式执行的。它也更快。
"""

"""
argparse是一个Python模块:命令行选项、参数和子命令解析器。
argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将
弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

description - 在参数帮助文档之前显示的文本(默认值:无)
formatter_class - 用于自定义帮助文档输出格式的类
RawDescriptionHelpFormatter 用于定制description和epilog,默认情况下description和epilog是自动换行的。
epilog - 在参数帮助文档之后显示的文本(默认值:无)
"""

parser.add_argument("-p", "--pid", type=int, default=-1,
        help="the PID to trace; if not specified, trace kernel allocs")
        根据PID去追溯;如果没有指定,则跟踪内核分配
//添加参数,定义程序需要的参数以及其默认值
'''
名字,type参数类型,default默认值,help:参数描述,metavar
选项字符串的名字 pid值,类型int,默认-1
'''
parser.add_argument("-t", "--trace", action="store_true",
        help="print trace messages for each alloc/free call")
        //action="store_true",存储True的值
        打印每个alloc / free调用的跟踪消息
parser.add_argument("interval", nargs="?", default=5, type=int,
        help="interval in seconds to print outstanding allocations")
        //nargs - 应该读取的命令行参数个数,可以是具体的数字,或者是?号
        打印未完成分配的时间间隔(以秒为单位)
parser.add_argument("count", nargs="?", type=int,
        help="number of times to print the report before exiting")
        退出前打印报表的次数
parser.add_argument("-a", "--show-allocs", default=False, action="store_true",
        help="show allocation addresses and sizes as well as call stacks")
        显示分配地址和大小以及调用堆栈
parser.add_argument("-o", "--older", default=500, type=int,
        help="prune allocations younger than this age in milliseconds")
        以毫秒为单位删除小于此年龄的分配
parser.add_argument("-c", "--command",
        help
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值