进程在heap分配的内存在VSS中有体现,分为shared和private,特别是private基本上和进程申请的内存相当。
/proc/pid/smaps中记录了进程的内存信息,写了一个c++程序来打印内存。
[winlin@dev6 utest]$ ./memview summary 28618
VMSIZE: 42240 KB
RSS: 1800 KB total
1352 KB shared
396 KB private clean
52 KB private dirty
进程28618占用了约1.8M内存。
同时提供了一个python的辅助工具,能按进程名称显示内存。
[winlin@dev6 utest]$ ./memview.py summary rtmp_server
command: ./memview summary 28618 for rtmp_server
VMSIZE: 42240 KB
RSS: 1800 KB total
1748 KB shared
0 KB private clean
52 KB private dirty
command: ./memview summary 28619 for rtmp_server
VMSIZE: 42240 KB
RSS: 708 KB total
652 KB shared
0 KB private clean
56 KB private dirty
/* compile as isolate program: g++ memview.cpp -o memview -g -O0 -D mem_view_self_main cli usage: ./memview [pid] pid: the pid of process to view memory. default to memview itself. api usage: MemView(pid).Print(); pid: 0, self, equals to getpid(). pid: > 0, get the memory stat of speicifed pid. pid: < 0, donot get the memory, use Calc(pid) to stat. # Copyright winlin. # you can distribute this under the MIT/X11 License */ #include <stdio.h> #include <stdlib.h> #include <string> #include <fstream> #include <iostream> #include <iomanip> #include <vector> #include <algorithm> #include <sstream> #include <assert.h> #include <unistd.h> using namespace std; class SmapsMemItem { public: string file; double vmsize; double rss; double pss; double shared_clean; double shared_dirty; double private_clean; double private_dirty; double reference; double swap; double kernel_page_size; double mmu_page_size; public: SmapsMemItem(){ } virtual ~SmapsMemItem(){ } public: bool operator > (const SmapsMemItem& o) const{ // if for private mapping. if(pss != 0){ // first by dirty, if(private_dirty > o.private_dirty){ return true; } // then by clean else if(private_dirty == o.private_dirty && private_clean > o.private_clean){ return true; } else{ return false; } } else{ if(shared_dirty > o.shared_dirty){ return true; } else if(shared_dirty == o.shared_dirty && shared_clean > o.shared_clean){ return true; } else{ return false; } } } bool operator < (const SmapsMemItem& o) const{ return !(*this > o); } public: bool Read(istream& fs){ static char skip[1024]; fs >> skip >> skip >> skip >> skip >> skip >> file; if(fs.eof()){ return false; } // no file if(file == "Size:"){ file = ""; } else{ fs >> skip; } fs >> vmsize; fs >> skip >> skip >> rss; fs >> skip >> skip >> pss; fs >> skip >> skip >> shared_clean; fs >> skip >> skip >> shared_dirty; fs >> skip >> skip >> private_clean; fs >> skip >> skip >> private_dirty; fs >> skip >> skip >> reference; fs >> skip >> skip >> swap; fs >> skip >> skip >> kernel_page_size; fs >> skip >> skip >> mmu_page_size; fs >> skip; return true; } void Print(){ cout << file << " vm:" << vmsize << " rss:" << rss << " pss:" << pss << " shared_clean:" << shared_clean << " shared_dirty:" << shared_dirty << " private_clean:" << private_clean << " private_dirty:" << private_dirty << " reference:" << reference << " swap:" << swap << " kernel_page_size:" << kernel_page_size << " mmu_page_size:" << mmu_page_size << endl; } void ItemPrint(bool print_private){ cout << setw(8) << fixed << setfill(' ') << vmsize << " kb" << setw(9) << fixed << setfill(' ') << ((print_private)? private_clean : shared_clean) << " kb" << setw(9) << fixed << setfill(' ') << ((print_private)? private_dirty : shared_dirty) << " kb" << setw(3) << fixed << setfill(' ') << " " << file << endl; } }; class MemView { private: int pid; private: vector<SmapsMemItem> private_items; vector<SmapsMemItem> shared_items; public: double vmsize; double rss; double shared_clean; // rss shared clean double shared_dirty; // rss shared dirty double private_clean; // rss private clean double private_dirty; // rss private dirty public: MemView(int pid = 0); virtual ~MemView(); private: void Clear(); private: bool Read(istream& fs); public: void Print(); public: void PrintSummary(); private: void PrintPrivateMappings(); public: void Calc(int pid); }; MemView::MemView(int pid){ this->pid = pid; if(pid >= 0){ Calc(pid); } } MemView::~MemView(){ } void MemView::Clear(){ vmsize = 0; rss = 0; shared_clean = 0; shared_dirty = 0; private_clean = 0; private_dirty = 0; shared_items.clear(); private_items.clear(); } bool MemView::Read(istream& fs){ Clear(); while(!fs.eof()){ SmapsMemItem o; if(!o.Read(fs)){ break; } if(o.pss == 0){ shared_items.push_back(o); } else{ private_items.push_back(o); } vmsize += o.vmsize; rss += o.rss; shared_clean += o.shared_clean; shared_dirty += o.shared_dirty; private_clean += o.private_clean; private_dirty += o.private_dirty; //o->Print(); } sort(shared_items.begin(), shared_items.end(), greater<SmapsMemItem>()); sort(private_items.begin(), private_items.end(), greater<SmapsMemItem>()); return true; } void MemView::Print(){ PrintSummary(); PrintPrivateMappings(); } void MemView::PrintSummary(){ cout.precision(0); cout << "VMSIZE:" << setw(11) << setfill(' ') << fixed << vmsize << " KB" << endl << "RSS:" << setw(14) << setfill(' ') << fixed << rss << " KB total" << endl << setw(18) << setfill(' ') << fixed << shared_clean + shared_dirty << " KB shared" << endl << setw(18) << setfill(' ') << fixed << private_clean << " KB private clean" << endl << setw(18) << setfill(' ') << fixed << private_dirty << " KB private dirty" << endl ; } void MemView::PrintPrivateMappings(){ if(private_items.size() == 0){ return; } cout.precision(0); cout << endl << "Private Mappings" << endl << setw(11) << fixed << setfill(' ') << "vmsize" << setw(12) << fixed << setfill(' ') << "rss clean" << setw(12) << fixed << setfill(' ') << "rss dirty" << setw(3) << fixed << setfill(' ') << " " << "file" << endl; vector<SmapsMemItem>::iterator ite; for(ite = private_items.begin(); ite != private_items.end(); ++ite){ SmapsMemItem& item = *ite; item.ItemPrint(true); } cout << endl << "Shared Mappings" << endl << setw(11) << fixed << setfill(' ') << "vmsize" << setw(12) << fixed << setfill(' ') << "rss clean" << setw(12) << fixed << setfill(' ') << "rss dirty" << setw(3) << fixed << setfill(' ') << " " << "file" << endl; for(ite = shared_items.begin(); ite != shared_items.end(); ++ite){ SmapsMemItem& item = *ite; item.ItemPrint(false); } } void MemView::Calc(int pid){ assert(pid >= 0); int actual_pid = pid; if(actual_pid == 0){ actual_pid = getpid(); } stringstream ss; ss << "/proc/" << actual_pid << "/smaps"; string file = ss.str(); //cout << "stat the file: " << file << endl; if(access(file.c_str(), R_OK) != 0){ cout << "process(#" << pid << ") does not exists! open file " << file << " error!" << endl; exit(-1); } fstream fs(file.c_str(), ios::in); Read(fs); fs.close(); } #ifdef mem_view_self_main int main(int argc, char** argv){ int pid = 0x0; string mode; if(argc <= 2){ cout << "Usage: " << argv[0] << " <mode> <pid>" << endl << " pid: the pid of process to view memory. 0: self." << endl << " mode: full or summary. full: print all info; summary: print summary only." << endl; exit(-1); } else{ mode = argv[1]; pid = atoi(argv[2]); } assert(pid >= 0); if(mode == "full"){ MemView(pid).Print(); } else{ MemView(pid).PrintSummary(); } return 0; } #endif
#!/usr/bin/python ''' usage: python memview.py <mode> <key> mode: full|summary. default is summary. key: the app name to view memory. default is rtmp_utest 1. compile if memview does not exist: g++ memview.cpp -o memview -g -O0 -D mem_view_self_main 2. find the rtmp_utest process and get its memory view: ps aux|grep rtmp_utest ./memview summary <pid> ''' import os, sys; if not os.path.exists("memview"): print "compile memview: g++ memview.cpp -o memview -g -O0 -D mem_view_self_main"; os.system("g++ memview.cpp -o memview -g -O0 -D mem_view_self_main"); if not os.path.exists("memview"): print "compile memview failed!"; sys.exit(-1); if len(sys.argv) <= 2: print "Usage %s <mode> <process_name>"%(sys.argv[0]); print " mode: summary or full."; print " process_name: the name of process."; print "For example: %s summary rtmp_server"%(sys.argv[0]); sys.exit(-1); mode = sys.argv[1]; key = sys.argv[2]; grep_key = "|grep %s"%(key); for s in ['_', '-', '.']: if s in key: grep_key = " ".join("|grep "+x+" " for x in key.split(s)); break; grep_command="ps aux %s"%(grep_key); p = os.popen(grep_command); lines = p.readlines(); p.close(); pid = None; got_one = False; for line in lines: if "sh -c" in line or sys.argv[0] in line: continue; pid = None; index = 0; while pid is None or len(pid) == 0 or not pid.isdigit(): pid = line.replace(" ", " ").split(" ")[index]; index += 1; if pid is None: print "cannot find process %s"%(key); sys.exit(-1); if len(pid) <= 0: print "cannot find the %s!!!"%(key); sys.exit(-1); got_one = True; cmd = "./memview %s %s"%(mode, pid); print "command: %s for %s"%(cmd, key); os.system(cmd); if not got_one: print 'cannot find process %s, grep= " %s "'%(key, grep_command);