⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exmap.cpp

📁 内存管理工具Exmap。该工具比 ps 或 top 更精确
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * (c) John Berthels 2005 <jjberthels@gmail.com>. See COPYING for license. */#include "jutil.hpp"#include "Exmap.hpp"#include "Elf.hpp"#include <sstream>#include <set>#include <ctype.h>#include <sys/types.h>#include <unistd.h>using namespace Exmap;using namespace std;using namespace jutil;using Elf::Address;ostream &operator<<(ostream &os, const Exmap::Process &proc){    proc.print(os);    return os;}ostream &operator<<(ostream &os, const Exmap::Map &map){    map.print(os);    return os;}// ------------------------------------------------------------Snapshot::Snapshot(SysInfoPtr &sys_info)    : _page_pool(new PagePool),      _file_pool(new FilePool),      _sys_info(sys_info){}const list<ProcessPtr> Snapshot::procs(){    return map_values(_procs);}const list<pid_t> Snapshot::pids(){    return map_keys(_procs);}		const ProcessPtr Snapshot::proc(pid_t pid){    ProcessPtr ret;    map<pid_t, ProcessPtr>::const_iterator it;    it = _procs.find(pid);    if (it != _procs.end()) {	ret = it->second;    }    return ret;}const list<FilePtr> Snapshot::files(){    return _file_pool->files();}const FilePtr Snapshot::file(const std::string &fname){    return _file_pool->name_to_file(fname);}bool Snapshot::load(){    list<pid_t> pids = _sys_info->accessible_pids();    if (!_sys_info->sanity_check()) {	warn << "Can't get system info\n";	exit(-1);    }    if (pids.empty()) {	warn << "Snapshot::load - can't get pid list\n";	return false;    }    if (!load_procs(pids)) {	warn << "Snapshot::load - failed to load: processe\n";	return false;    }        if (!calculate_file_mappings()) {    	warn << "Snapshot::load - failed to load: calculate file mappings\n";    	return false;    }    return true;}bool Snapshot::load_procs(const list<pid_t> &pids){    list<pid_t>::const_iterator it;    pid_t mypid = getpid();    _procs.clear();    _page_pool->clear();        for (it = pids.begin(); it != pids.end(); ++it) {	if (*it == mypid) {	    // Don't monitor ourselves	    continue;	}	ProcessPtr proc(new Process(_page_pool, *it));	proc->selfptr(proc);	if (!proc->load(_sys_info)) {	    warn << "Snapshot::load_procs - can't load pid " << *it << "\n";	    continue;	}	if (proc->has_mm()) {	    _procs[*it] = proc;	}    }        return !_procs.empty();}bool Snapshot::calculate_file_mappings(){    list<ProcessPtr>::iterator it;    list<ProcessPtr> processes = procs();    for (it = processes.begin(); it != processes.end(); ++it) {	if (!(*it)->calculate_maps(_file_pool)) {	    warn << "Failed to process maps for pid " << (*it)->pid() << "\n";	    return false;	}    }    return !_file_pool->files().empty();}// ------------------------------------------------------------void PagePool::clear(){    _counts.clear();}// ------------------------------------------------------------void FilePool::clear(){    _files.clear();}FilePtr FilePool::name_to_file(const string &name){    return _files[name];}FilePtr FilePool::get_or_make_file(const string &name){    map<string, FilePtr>::iterator it;    it = _files.find(name);    if (it == _files.end()) {	FilePtr f(new File(name));	_files[name] = f;	it = _files.find(name);    }    return it->second;}list<FilePtr> FilePool::files(){    return map_values(_files);}// ------------------------------------------------------------Process::Process(const PagePoolPtr &page_pool,		 pid_t pid)    : _pid(pid),      _page_pool(page_pool){ }const PagePoolPtr &Process::page_pool(){    return _page_pool;}boost::shared_ptr<Process> Process::selfptr(){    return _selfptr.lock();}void Process::selfptr(boost::shared_ptr<Process> &p){    _selfptr = p;}bool Process::load(SysInfoPtr &sys_info){    _cmdline = sys_info->read_cmdline(_pid);    if (_cmdline.empty()) {	_cmdline = "[nocmdline]";    }    if (!sys_info->read_vmas(_page_pool, _pid, _vmas)) {	warn << "Process::load - can't load vmas: " << _pid << "\n";	return false;    }    // Can't load pages if we don't have any...    if (!has_mm()) { return true; }        if (!load_page_info(sys_info)) {	warn << "Process::load - can't load page info: " << _pid << "\n";	return false;    }    remove_vdso_if_nopages();    return true;}void Process::remove_vdso_if_nopages(){    stringstream pref;    pref << pid() << " remove_vdso_if_nopages: ";    list<VmaPtr>::iterator it;        for (it = _vmas.begin(); it != _vmas.end(); ++it) {	if ((*it)->is_vdso() && (*it)->num_pages() == 0) {	    dbg << pref.str() << "removing\n";	    _vmas.erase(it);	    return;	}    }}string Process::cmdline(){    return _cmdline;}list<FilePtr> Process::files(){    list<FilePtr> files(_files.begin(), _files.end());    return files;}pid_t Process::pid(){    return _pid;}SizesPtr Process::sizes(){    return Map::sum_sizes(_page_pool, _maps);}SizesPtr Process::sizes(const FilePtr &file){    list<MapPtr> maps;    maps = restrict_maps_to_file(file);    return Map::sum_sizes(_page_pool, maps);}SizesPtr Process::sizes(const FilePtr &file,			const RangePtr &elf_range){    list<MapPtr> maps;    list<MapPtr>::iterator it;    maps = restrict_maps_to_file(file);    SizesPtr sizes(new Sizes);    for (it = maps.begin(); it != maps.end(); ++it) {	RangePtr map_elf_range = (*it)->elf_range();	if (map_elf_range) {	    RangePtr subrange = elf_range->intersect(*map_elf_range);	    if (subrange) {		RangePtr mem_range = (*it)->elf_to_mem_range(subrange);		SizesPtr subsizes = (*it)->sizes_for_mem_range(_page_pool,							       mem_range);		if (subsizes) {		    sizes->add(subsizes);		}	    }	}    }    return sizes;}list<MapPtr> Process::restrict_maps_to_file(const FilePtr &file){    list<MapPtr> result;    list<MapPtr> file_maps = file->maps();    list<MapPtr> proc_maps = _maps;    file_maps.sort();    proc_maps.sort();    dbg << _pid << ": " << "rmtf " << file->name() << ": "	<< proc_maps.size() << " procs "	<< file_maps.size() << " files\n";        while (!file_maps.empty() && !proc_maps.empty()) {	if (file_maps.front() == proc_maps.front()) {	    result.push_back(proc_maps.front());	    proc_maps.pop_front();	    file_maps.pop_front();	}	else if (file_maps.front() < proc_maps.front()) {	    file_maps.pop_front();	}	else {	    proc_maps.pop_front();	}    }    if (result.size() == 0) {	warn << _pid << ": empty restriction to file " << file->name() << "\n";    }    return result;}void Process::add_file(const FilePtr &file){    _files.insert(file);}bool Process::calculate_maps(FilePoolPtr &file_pool){    MapCalculator mc(_vmas, file_pool, selfptr());    return mc.calc_maps(_maps) && !_maps.empty();}bool Process::load_page_info(SysInfoPtr &sys_info){    map<Address, list<Page> > page_info;    stringstream pref;    pref << pid() << " load_page_info: ";    if (!sys_info->read_page_info(_pid, page_info)) {	warn << pref.str() << "can't read page info for " << _pid;	return false;    }    map<Address, list<Page> >::iterator pi_it;    for (pi_it = page_info.begin(); pi_it != page_info.end(); ++pi_it) {	Address start_address = pi_it->first;	VmaPtr vma;	if (!find_vma_by_addr(start_address, vma)) {	    // This can happen, a process can alloc whilst we are	    // running	    warn << pref.str() << "can't find vma at "		 << hex << start_address << dec << ": " << _pid << "\n";	    continue;	}		if (pi_it->second.size() == 0) {	    warn << pref.str() << "VMA with no pages " << start_address << "\n";	}	vma->add_pages(pi_it->second);	_page_pool->inc_pages_count(pi_it->second);    }    return true;}bool Process::has_mm(){    return _vmas.size() > 0;}bool Process::find_vma_by_addr(Address start,				VmaPtr &vma){    list<VmaPtr>::const_iterator it;    for (it = _vmas.begin(); it != _vmas.end(); ++it) {	if ((*it)->start() == start) {	    vma = *it;	    return true;	}    }    return false;}void Process::print(ostream &os) const{    os << "PID: " << _pid << "\n"	<< "CMD: " << _cmdline << "\n";    std::list<MapPtr>::const_iterator map_it;    for (map_it = _maps.begin(); map_it != _maps.end(); ++map_it) {	os << **map_it << "\n";    }    os << "\n";}// ------------------------------------------------------------Vma::Vma(Elf::Address start,	 Elf::Address end,	 off_t offset,	 const std::string &fname)    : _offset(offset),      _fname(fname){    _range = RangePtr(new Range(start, end));}Elf::Address Vma::start() { return _range->start(); }Elf::Address Vma::end() { return _range->end(); }RangePtr Vma::range() { return _range; }std::string Vma::fname() { return _fname; }off_t Vma::offset() { return _offset; }Elf::Address Vma::vm_size() { return _range->size(); }int Vma::num_pages(){    return _pages.size();}boost::shared_ptr<Vma> Vma::selfptr(){    return _selfptr.lock();}void Vma::selfptr(boost::shared_ptr<Vma> &p){    _selfptr = p;}    void Vma::add_pages(const list<Page> &pages){    list<Page>::const_iterator it;    for (it = pages.begin(); it != pages.end(); ++it) {	_pages.push_back(*it);    }}bool Vma::is_vdso(){    return fname() == "[vdso]";}bool Vma::is_file_backed(){    string::size_type pos = _fname.length();    if (pos == 0) {	warn << "Zero length file name in vma\n";	return false;    }    // Names like [vdso], [anon], [stack] etc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -