首页 新闻 会员 周边

chrome的源码中有一个memorywatcher的东西,看着挺麻烦的,有人了解吗?可否大体讲一下工作流程?

0
悬赏园豆:100 [已解决问题] 解决于 2012-03-12 18:11

chrome的源码中有一个memorywatcher的东西,看着挺麻烦的,有人了解吗?可否大体讲一下工作流程?

木头人一号的主页 木头人一号 | 初学一级 | 园豆:11
提问于:2012-03-12 17:06
< >
分享
最佳答案
0

MemoryWatcher在win平台下是dll形式载入工程的,内嵌stackwalker,hook了win平台下常用的内存申请释放方法,对内存申请释放等进行记录。根据动态内存操作方式之间单一的层次关系(Windows平台下的内存管理),dll载入初始化的时候,对win平台下原有的内存申请方法进行了方法注入,调用内部实现的方法在进程堆上分配释放存储,完成了基本的申请释放跟踪。win平台下可以基于MemoryWatcher实现你所需要的功能,如果是linux平台,可能chrome的linux版也是有这个功能模块的,自行参考一下就好了。

最主要的几个类:MemoryWatcher,MemoryHook,CallStack(参考visualleakdetectorStackWalker)

MemoryWatcher 主要完成方法的hook,以及监测内存的分配与释放。

  1. classMemoryWatcher:MemoryObserver{
  2. public:
  3. // Dump all tracked pointers still in use.
  4. voidDumpLeaks();
  5. // 申请存储的时候进行跟踪管理
  6. virtualvoidOnTrack(HANDLE heap, int32 id, int32 size);
  7. // 释放存储的时候释放跟踪
  8. virtualvoidOnUntrack(HANDLE heap, int32 id, int32 size);
  9. private:
  10. // 提供日志管理操作
  11. voidOpenLogFile();
  12. voidCloseLogFile();
  13. // 存储申请释放相关方法hook
  14. voidHook();
  15. // 释放存储相关方法hook
  16. voidUnhook();
  17. // 利用hash提供快速的跟踪(查找删除等)
  18. // The block_map provides quick lookups based on the allocation
  19. // pointer.  This is important for having fast round trips through
  20. // malloc/free.
  21. CallStackMap*block_map_;
  22. }

MemoryHook 主要完成模块内部使用的存储分配工作,内部使用的空间只能是在MemoryHook维护的堆空间上,否则会造成死循环,
同时MemoryHook完成MemoryWatcher的全局注册,内存的分配释放行为都会通知给注册的MemoryWatcher。

  1. classMemoryHook:MemoryObserver{
  2. public:
  3. // Initialize the MemoryHook.  Must be called before
  4. // registering watchers.  This can be called repeatedly,
  5. // but is not thread safe.
  6. staticboolInitialize();
  7. // Register a class to receive memory allocation & deallocation
  8. // callbacks.  If we haven't hooked memory yet, this call will
  9. // force memory hooking to start.
  10. staticboolRegisterWatcher(MemoryObserver* watcher);
  11. // Register a class to stop receiving callbacks.  If there are
  12. // no more watchers, this call will unhook memory.
  13. staticboolUnregisterWatcher(MemoryObserver* watcher);
  14. // 内部使用的存储空间不受监控,需要在私有堆空间内申请释放
  15. // MemoryHook provides a private heap for allocating
  16. // unwatched memory.
  17. staticvoid*Alloc(size_t size){
  18. DCHECK(global_hook_ && global_hook_->heap_);
  19. returnHeapAlloc(global_hook_->heap_,0, size);
  20. }
  21. staticvoidFree(void* ptr){
  22. DCHECK(global_hook_ && global_hook_->heap_);
  23. HeapFree(global_hook_->heap_,0, ptr);
  24. }
  25. }

在dll入口方法,如下,监测者对象MemoryWatcher的创建,MemoryWatcher调用Hook方法完成内存相关操作的hook,同时完成CallStack初始化操作,将MemoryWatcher注册给MemoryHook以接收内存申请释放消息。入口方法中还创建了一个后台线程监测关键事件,注入heap句柄或指针无效等等,发生此类事情的时候可以生成转储记录日志等。

  1. BOOL WINAPI DllMain(HINSTANCE dll_instance, DWORD reason,
  2. LPVOID reserved){
  3. if(!IsChromeExe())
  4. return FALSE;
  5. switch(reason){  
  6. case DLL_PROCESS_ATTACH:
  7. CreateMemoryWatcher();
  8. CreateBackgroundThread();
  9. break;
  10. case DLL_PROCESS_DETACH:
  11. DeleteMemoryWatcher();
  12. StopBackgroundThread();
  13. break;
  14. }
  15. return TRUE;
  16. }

上面说过这里是通过hook内存申请释放方法辅助监测的,hook发生在MemoryHook::Hook()中,涵盖所有可能的申请释放行为:

  1. boolMemoryHook::Hook(){
  2. DCHECK(!hooked_);
  3. if(!hooked_){
  4. DCHECK(global_hook_);
  5. // Luckily, Patch() doesn't call malloc or windows alloc routines
  6. // itself -- though it does call new (we can use PatchWithStub to
  7. // get around that, and will need to if we need to patch new).
  8. HMODULE hkernel32 =::GetModuleHandle(L"kernel32");
  9. CHECK(hkernel32 != NULL);
  10. HMODULE hntdll =::GetModuleHandle(L"ntdll");
  11. CHECK(hntdll != NULL);
  12. // Now that we've found all the functions, patch them
  13. INSTALL_PATCH(HeapCreate);
  14. INSTALL_PATCH(HeapDestroy);
  15. INSTALL_PATCH(HeapAlloc);
  16. INSTALL_PATCH(HeapReAlloc);
  17. INSTALL_PATCH(HeapFree);
  18. INSTALL_PATCH(VirtualAllocEx);
  19. INSTALL_PATCH(VirtualFreeEx);
  20. INSTALL_PATCH(MapViewOfFileEx);
  21. INSTALL_PATCH(MapViewOfFile);
  22. INSTALL_PATCH(UnmapViewOfFile);
  23. INSTALL_NTDLLPATCH(NtUnmapViewOfSection);
  24. INSTALL_PATCH(GlobalAlloc);
  25. INSTALL_PATCH(GlobalReAlloc);
  26. INSTALL_PATCH(GlobalFree);
  27. INSTALL_PATCH(LocalAlloc);
  28. INSTALL_PATCH(LocalReAlloc);
  29. INSTALL_PATCH(LocalFree);
  30. // We are finally completely hooked.
  31. hooked_ =true;
  32. }
  33. returntrue;
  34. }

举例INSTALL_PATCH的实现,记录来时的路,不然回不了家。

  1. // Macro to install Patch functions.
  2. #define INSTALL_PATCH(name)  do{                                       \
  3. patch_##name.set_original(GET_PROC_ADDRESS(hkernel32, ##name));       \
  4. patch_##name.Install(&Perftools_##name);                              \
  5. }while(0)

install过程稍微麻烦一些,感兴趣的话可以自己看一下,在preamble_patcher.cc
举例HeapAlloc与HeapFree的HeapFree"替代者",内部调用了MemoryHook的hook,后者调用了MemoryWatcher的hook,MemoryWatcher的hook中对存储进行跟踪记录。

  1. static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
  2. DWORD_PTR dwBytes){
  3. LPVOID rv = patch_HeapAlloc()(hHeap, dwFlags, dwBytes);
  4. MemoryHook::hook()->OnTrack(hHeap,reinterpret_cast<int32>(rv), dwBytes);
  5. return rv;
  6. }
  7. static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
  8. LPVOID lpMem){
  9. size_t size =0;
  10. if(lpMem !=0){
  11. size =HeapSize(hHeap,0, lpMem);  // Will crash if lpMem is 0.
  12. // Note: size could be 0; HeapAlloc does allocate 0 length buffers.
  13. }
  14. MemoryHook::hook()->OnUntrack(hHeap,reinterpret_cast<int32>(lpMem), size);
  15. return patch_HeapFree()(hHeap, dwFlags, lpMem);
  16. }


收获园豆:80
zsounder | 老鸟四级 |园豆:2819 | 2012-03-12 18:08
其他回答(1)
0

内存查看器吧,这篇文章http://blog.csdn.net/v_july_v/article/details/6296329有讲解,希望有帮助

收获园豆:20
az235 | 园豆:8483 (大侠五级) | 2012-03-12 17:15
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册