程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 軟件調試技術(2)-- coredump如何實現

軟件調試技術(2)-- coredump如何實現

編輯:關於PHP編程

軟件調試技術(2)-- coredump如何實現


最近在工作中了解到應用軟件在崩潰的時候可以設置生成轉存文件,這個功能就是coredump。不論是應用程序崩潰還是kernel崩潰轉存功能都是很實用技術。本文是想從實現原理角度來理解這兩項技術實現方法。首先分析一下應用程序coredump的實現方法。

什麼條件觸發轉存
這個轉存發生在應用程序收到致命的signal,在處理這個signal的時候會執行應用程序的轉存,並在之後退出執行。有一點必須注意,如果用戶給這些致命signal安裝了自定義的handler,轉存是不會發生的。OK,那麼這裡總結出兩點:
1,致命signal會出發轉存發生,這些signal包括如下內容。

  1. 398 #define SIG_KERNEL_COREDUMP_MASK(\
  2. 399 rt_sigmask(SIGQUIT)|rt_sigmask(SIGILL)|\
  3. 400 rt_sigmask(SIGTRAP)|rt_sigmask(SIGABRT)|\
  4. 401 rt_sigmask(SIGFPE)|rt_sigmask(SIGSEGV)|\
  5. 402 rt_sigmask(SIGBUS)|rt_sigmask(SIGSYS)|\
  6. 403 rt_sigmask(SIGXCPU)|rt_sigmask(SIGXFSZ)|\
  7. 404 SIGEMT_MASK
2,如果上面的致命signal被用戶安裝了自定義的處理函數,coredump也不會發生。

  1. 2264if(ka->sa.sa_handler!=SIG_DFL){
  2. 2265/*Run the handler.*/
  3. 2266 ksig->ka=*ka;
  4. 2267
  5. 2268if(ka->sa.sa_flags&SA_ONESHOT)
  6. 2269 ka->sa.sa_handler=SIG_DFL;
  7. 2270
  8. 2271 break;/*will return non-zero"signr"value*/
  9. 2272}
在kernel查找需要處理的signal的時候,首先會判斷這個signal是不是默認處理方式,如果是默認處理才會繼續執行到coredump分支,否則跳出查找環節,執行用戶自定義處理方式。

觸發coredump執行的分支

  1. 2335if(sig_kernel_coredump(signr)){
  2. 2336if(print_fatal_signals)
  3. 2337 print_fatal_signal(ksig->info.si_signo);
  4. 2338 proc_coredump_connector(current);
  5. 2339/*
  6. 2340*Ifit was abletodump core,this kills all
  7. 2341*other threadsinthe groupandsynchronizes with
  8. 2342*their demise.Ifwe lost the race with another
  9. 2343*thread getting here,itsetgroup_exit_code
  10. 2344*firstandour do_group_exitcallbelow will use
  11. 2345*that valueandignore the one we pass it.
  12. 2346*/
  13. 2347 do_coredump(&ksig->info);
  14. 2348}


將致命signal打印到控制台的Tips
如果你開啟如下proc目錄下的option,將開啟打印致命signal到控制台的功能。
/proc/sys/kernel/print-fatal-signals

coredump主要步驟
其實將這個應用程序都寫入到磁盤的過程肯定是非常負責的。這裡我不會扣沒一個細節,有一些原理性的細節可能推到後面的部分再詳細學習和分析。但是,這裡我們需要了解如下幾個關於coredump的關鍵處理流程。
1, coredump之間,首先要檢查線程組中所有線程是不是已經都進入到了休眠狀態。我們要coredump必須保證我們在拷貝這個進程的內存空間的時候進程中的某些線程還在運行並改寫內存空間。
2, 對於直接將進程內存轉存到文件的情況,沒有什麼特別之處,就是打開一個文件,並開始寫入。
3,對於制定了用戶空間腳本,進行一些壓縮操作的情況,這裡會啟動一個用戶態進程,並在kernel和用戶態進程之間建立一個管道,
kernel=========讀出===========用戶態進程(壓縮)-----------寫入-------->文件

對於第一步處理,kernel想進程組中所有的線程發送kill signal信號,然後等待所有進程都不處在運行狀態。
對於第二步,處理相對簡單,只是之後如果有興趣還可深入研究一下coredump文件的格式到底是什麼樣子的。
第三步,相對比較復雜,比較巧妙的地方就是在kernel中建立了一條管道,kernel處理signal部分將coredump寫入管道,而新建的進程中管道的另外一端被設置到了標准輸入上面。

對於壓縮進程轉存的方法
我們可以興建一個shell執行文件
#!/bin/sh
execgzip->/root/$1.core.$2.gz
然後在/proc/sys/kernel/core_pattern 中寫入
|/usr/sbin/core_helper%e%p

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved