日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

崩溃优化(一)

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 崩溃优化(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android 兩種崩潰

  • Java崩潰
    • 在Java代碼中出現了未捕獲的異常,導致程序異常退出
  • Native崩潰
    • 在Native代碼中訪問非法地址或地址對齊出現問題或者程序主動 abort 異常退出 (默認的程序結束函數,這種方式可能會或可能不會以刷新與關閉打開的文件或刪除臨時文件)

Native崩潰捕獲機制以及實現

  • 首先native crash因為具有上下文不全,出錯信息模糊,難以捕捉的特點,所以捕獲難比Java crash更難修復
    • 所以捕獲組件需要達到以下特點
      • 打印logcat和應用日志
      • 上報crash次數
      • 對不同的crash做不同的恢復措施
      • 可以針對業務不斷改進和適應

信號機制

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CkfcxK6b-1570331077566)(en-resource://database/8399:1)]

  • 在Unix-like系統中,所有的崩潰都是編程錯誤或者硬件錯誤相關的,系統遇到不可恢復的錯誤時會觸發崩潰時機讓程序退出
  • 異常發生時,CPU通過異常中斷的方式觸發異常處理流程,不同的處理器,有不同的異常中斷處理方式
  • 在Linux系統中,這些中斷處理統稱為信號量,可以注冊信號量向量進行處理
  • 信號(軟中斷信號)機制是進程之間信息傳遞的一種方法
    • 當函數運行在用戶態時,當遇到系統調用、中斷或是異常的情況時,程序會進入內核態,信號的處理就在這兩種狀態之間相互轉換

信號類型

SignalDescription
SIGABRT由調用abort函數產生,進程非正常退出
SIGALRM用alarm函數設置的timer超時或setitimer函數設置的interval timer超時
SIGBUS某種特定的硬件異常,通常由內存訪問引起
SIGCANCEL由Solaris Thread Library內部使用,通常不會使用
SIGCHLD進程Terminate或Stop的時候,SIGCHLD會發送給它的父進程。缺省情況下該Signal會被忽略
SIGCONT當被stop的進程恢復運行的時候,自動發送
SIGEMT和實現相關的硬件異常
SIGFPE數學相關的異常,如被0除,浮點溢出,等等
SIGFREEZESolaris專用,Hiberate或者Suspended時候發送
SIGHUP發送給具有Terminal的Controlling Process,當terminal被disconnect時候發送
SIGILL非法指令異常
SIGINFOBSD signal。由Status Key產生,通常是CTRL+T。發送給所有Foreground Group的進程
SIGINT由Interrupt Key產生,通常是CTRL+C或者DELETE。發送給所有ForeGround Group的進程
SIGIO異步IO事件
SIGIOT實現相關的硬件異常,一般對應SIGABRT
SIGKILL無法處理和忽略。中止某個進程
SIGLWP由Solaris Thread Libray內部使用
SIGPIPE在reader中止之后寫Pipe的時候發送
SIGPOLL當某個事件發送給Pollable Device的時候發送
SIGPROFSetitimer指定的Profiling Interval Timer所產生
SIGPWR和系統相關。和UPS相關。
SIGQUIT輸入Quit Key的時候(CTRL+\)發送給所有Foreground Group的進程
SIGSEGV非法內存訪問
SIGSTKFLTLinux專用,數學協處理器的棧異常
SIGSTOP中止進程。無法處理和忽略。
SIGSYS非法系統調用
SIGTERM請求中止進程,kill命令缺省發送
SIGTHAWSolaris專用,從Suspend恢復時候發送
SIGTRAP實現相關的硬件異常。一般是調試異常
SIGTSTPSuspend Key,一般是Ctrl+Z。發送給所有Foreground Group的進程
SIGTTIN當Background Group的進程嘗試讀取Terminal的時候發送
SIGTTOU當Background Group的進程嘗試寫Terminal的時候發送
SIGURG當out-of-band data接收的時候可能發送
SIGUSR1用戶自定義signal 1
SIGUSR2用戶自定義signal 2
SIGVTALRMsetitimer函數設置的Virtual Interval Timer超時的時候
SIGWAITINGSolaris Thread Library內部實現專用
SIGWINCH當Terminal的窗口大小改變的時候,發送給Foreground Group的所有進程
SIGXCPU當CPU時間限制超時的時候
SIGXFSZ進程超過文件大小限制
SIGXRESSolaris專用,進程超過資源限制的時候發送

信號處理流程

  • 信號的接收

    • 接收信號是由內核代理的,當內核接收到信號后,會將其放到對應的進程信號隊列中,同時向進程中發送一個中斷,使其陷入內核態,注意,此時信號還只是在隊列中,對進程來說暫時是不知道有信號的到來
  • 信號的檢測

    • 進程陷入內核態后,有兩種場景會對信號進行檢測:
      • 進程從內核態返回到用戶態前進行信號檢測
      • 進程在內核態中,從睡眠狀態到被喚醒時進行信號檢測
  • 信號的處理

    • 運行在用戶態,調用函數處理前,內核會將當前內核棧的內容備份拷貝到用戶棧上,并且修改指令寄存器將其指向信號處理函數
    • 接著進程返回到用戶態中,執行相應的信號處理函數
    • 信號處理函數執行完成后,還需要返回內核態,檢查是否還有信號未作處理,如果所欲信號都處理完成,就會將內核棧恢復,同時恢復指令寄存器將其指向終端前的運行位置,最后回到用戶態繼續執行進程

捕捉native crash

  • 注冊信號處理函數
//signum:信號編碼 //act:指向結構體sigaction的一個實例的指針,該實例指定了對特定信號的處理,如果設置為空,進程會執行默認處理 //oldact:和參數act類似,只不過保存的是原來對相應信號的處理,也可設置為NULL #include <signal.h> int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact)); struct sigaction sa_old; ? memset(&sa, 0, sizeof(sa)); ? sigemptyset(&sa.sa_mask); ? sa.sa_sigaction = my_handler; ? sa.sa_flags = SA_SIGINFO; if (sigaction(sig, &sa, &sa_old) == 0) { ? ... ? }
  • 設置額外棧空間
#include <signal.h> int sigaltstack(const stack_t *ss, stack_t *oss); stack_t stack;??? memset(&stack, 0, sizeof(stack));?? /* Reserver the system default stack size. We don't need that much by the way. */?? stack.ss_size = SIGSTKSZ;??? stack.ss_sp = malloc(stack.ss_size);??? stack.ss_flags = 0;?? /* Install alternate stack size. Be sure the memory region is valid until you revert it. */?? if (stack.ss_sp != NULL && sigaltstack(&stack, NULL) == 0) {????...???}

兼容其他signal處理

static void my_handler(const int code, siginfo_t *const si, void *const sc) { ... ? ?/* Call previous handler. */ ? ?old_handler.sa_sigaction(code, si, sc); ? }

Breakpad

  • Breakpad是目前Native崩潰中最成熟的方案,
  • google-breakpad有兩種工作模式。進程內和進程外抓取
    • 進程內模式通過使用exception_handle模塊完成,使用也非常簡單——實例化ExceptionHandler,在構造函數中注冊回調FilterCallback和MinidumpCallback以及dump文件路徑即可,前者Filter回調發生在崩潰之后,dump回調寫入dump文件之間,在exception_handler.h中有詳盡注釋,毋庸贅言

    • 進程外模式采用一個守護進程與崩潰進程進程間通訊的模式實現,xl當年的后臺網頁查毒也是使用這種結構,只是實現更笨重。這兩種模式是排他的,進程外模式需要崩潰進程和監聽者進程分別引入crash_generation_client和crash_generation_server

安裝和編譯

  • 編譯環境
    • python 2.7
    • windows sdk 7
    • VS2005的補丁
  • 資源下載
svn checkout http://google-breakpad.googlecode.com/svn/trunk/?google-breakpad-read-only
  • 設置windows sdk 7
運行開始菜單->程序->Microsoft Windows SDK v7.0->Visual Studio Registration->Windows SDK Configuration Tool,選擇v7.0,點擊Make Current
  • 生成windows工程文件
cd?"源碼目錄/src/tools/gyp" //注意,此處不能使用全路徑,不然會出錯 gyp.bat?"../../client/windows/breakpad_client.gyp"

使用Breakpad

  • 進程內抓取Dump文件
const std::wstring s_strCrashDir = L"c:\dumps"; bool InitBreakpad() {google_breakpad::ExceptionHandler *pCrashHandler =new google_breakpad::ExceptionHandler(s_strCrashDir,onExceptionFilter,onMinidumpDumped,NULL,google_breakpad::ExceptionHandler::HANDLER_ALL,MiniDumpNormal,NULL,NULL);if(pCrashHandler == NULL) {return false;}return true; }
  • 進程外抓取Dump文件
    • 使用進程外抓取Dump時,需要指定服務端和客戶端,在服務端中需要創建CrashGenerationServer的實例,而在客戶端中則只需要創建ExceptionHandler即可。此外,如果服務端自己需要抓進程內的Dump,請將pipe的參數置為NULL
const wchar_t s_pPipeName[] = L"\\.\pipe\breakpad\crash_handler_server"; const std::wstring s_strCrashDir = L"c:\dumps"; bool InitBreakpad() {google_breakpad::CrashGenerationServer *pCrashServer =new google_breakpad::CrashGenerationServer(s_pPipeName,NULL,onClientConnected,NULL,onClientDumpRequest,NULL,onClientExited,NULL,true,&s_strCrashDir);if(pCrashServer == NULL) {return false;}// 如果已經服務端已經啟動了,此處啟動會失敗if(!pCrashServer->Start()) {delete pCrashServer;pCrashServer = NULL;}google_breakpad::ExceptionHandler *pCrashHandler =new google_breakpad::ExceptionHandler(s_strCrashDir,onExceptionFilter,onMinidumpDumped,NULL,google_breakpad::ExceptionHandler::HANDLER_ALL,MiniDumpNormal,(pCrashServer == NULL) ? s_pPipeName : NULL, // 如果是服務端,則直接使用進程內dumpNULL);if(pCrashHandler == NULL) {return false;}return true; }

總結

以上是生活随笔為你收集整理的崩溃优化(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。