如何准确地执行子进程后的最大内存使用量?

时间:2013-09-02 03:04:36

标签: linux

我编写了一个程序,用于监视子进程的资源。我使用wait4函数的第四个参数来获取子进程的CPU使用率,这很好。但我可以用它来获取内存,它看起来与“ps”的输出不同。我也尝试解析/ proc / pid / status,但有时它不准确,因为某些子进程太快无法解析。谁能给我一些建议或解决方案?非常感谢。

1 个答案:

答案 0 :(得分:2)

一旦进程终止,即使进程条目仍然存在于内核中,内核也会释放该进程的所有资源。所以,我不希望能够从/ proc。

读取进程的内存大小

此外,该过程没有“使用的最大内存”统计信息。

我可以考虑确定进程的最大内存量的唯一方法如下:

  1. 在执行过程中定期对进程状态进行采样并获取当前内存使用情况,
  2. 使用strace捕获进程发出的所有系统调用并对其进行处理,以确定进程使用了​​多少内存,或者
  3. 使用共享库拦截进程创建的内存分配系统调用,捕获详细信息并找到报告方式
  4. 除非绝对需要非常高的准确度,否则我可能会选择(1)。

    可能有分析或统计工具来帮助完成此任务,但我不知道。


    使用Strace

    这是一个程序,用于说明strace用于此目的:

    <强> allocit.c

    #include <stdio.h>
    #include <stdlib.h>
    
    int main ()
    {
            int     cur;
    
            cur = 0;
            while ( cur < 1000 )
            {
                    malloc(1024);
                    cur++;
            }
    
            return  0;
    }
    

    使用strace(strace ./allocit)运行此输出会得到如下输出:

    execve("./allocit", ["./allocit"], [/* 49 vars */]) = 0
    brk(0)                                  = 0x1b991000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dccd000
    uname({sys="Linux", node="fearless.office.tmcs", ...}) = 0
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    open("/home/jdoe/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/home/jdoe/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/home/jdoe/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/home/jdoe/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/home/jdoe/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/home/jdoe/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/home/jdoe/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/home/jdoe/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    open("/software/ticketmaster/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/software/ticketmaster/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/software/ticketmaster/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/software/ticketmaster/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/software/ticketmaster/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/software/ticketmaster/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/software/ticketmaster/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/software/ticketmaster/lib", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/usr/lib/oracle/11.2/client64/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/usr/lib/oracle/11.2/client64/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/usr/lib/oracle/11.2/client64/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/usr/lib/oracle/11.2/client64/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/usr/lib/oracle/11.2/client64/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/usr/lib/oracle/11.2/client64/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
    open("/usr/lib/oracle/11.2/client64/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat("/usr/lib/oracle/11.2/client64/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=123338, ...}) = 0
    mmap(NULL, 123338, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ae49dcce000
    close(3)                                = 0
    open("/lib64/libc.so.6", O_RDONLY)      = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\332!\2359\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=1717800, ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dced000
    mmap(0x399d200000, 3498328, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x399d200000
    mprotect(0x399d34e000, 2093056, PROT_NONE) = 0
    mmap(0x399d54d000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14d000) = 0x399d54d000
    mmap(0x399d552000, 16728, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x399d552000
    close(3)                                = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dcee000
    arch_prctl(ARCH_SET_FS, 0x2ae49dcee210) = 0
    mprotect(0x399d54d000, 16384, PROT_READ) = 0
    mprotect(0x399d01b000, 4096, PROT_READ) = 0
    munmap(0x2ae49dcce000, 123338)          = 0
    brk(0)                                  = 0x1b991000
    brk(0x1b9b2000)                         = 0x1b9b2000
    brk(0x1b9d3000)                         = 0x1b9d3000
    brk(0x1b9f4000)                         = 0x1b9f4000
    brk(0x1ba15000)                         = 0x1ba15000
    brk(0x1ba36000)                         = 0x1ba36000
    brk(0x1ba57000)                         = 0x1ba57000
    brk(0x1ba78000)                         = 0x1ba78000
    brk(0x1ba99000)                         = 0x1ba99000
    exit_group(0)                           = ?
    

    注意用于扩展堆的所有brk()调用。