linux:core文件的產生和調試


轉自:https://www.jianshu.com/p/e38a3f1cf7f7

在Linux下程序不尋常退出時,內核會在當前工作目錄下生成一個core文件(是一個內存映像,同時加上調試信息)。使用gdb來查看core文件,可以指示出導致程序出錯的代碼所在文件和行數。

注: 1. 當然首先編譯時要帶上gdb信息

1. core文件的生成開關和大小限制

1.1使用ulimit -c命令可查看core文件的生成開關。

若結果為0,則表示關閉了此功能,不會生成core文件。

1.2 使用ulimit -c filesize命令,可以限制core文件的大小(filesize的單位為kbyte)。

如果生成的信息超過此大小,將會被裁剪,最終生成一個不完整的core文件或者根本就不生成。
如果生成被裁減的core文件,調試此core文件的時候,gdb也會提示錯誤。
用以下命令來表示core文件的大小不受限制。

ulimit -c unlimited

用以下命令來阻止系統生成core文件:

 ulimit -c 0

下面的命令可以檢查生成core文件的選項是否打開:

ulimit -a

該命令將顯示所有的用戶定制,其中選項-a代表“all”。

$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) 4 max memory size (kbytes, -m) unlimited open files (-n) 2048 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7168 virtual memory (kbytes, -v) unlimited 

注:
a) ulimit命令設置后只對一個終端有效,所以另起終端后需要重新設置。
b) 要在整個系統中生效,可以通過如下方法(當然此方法未必管用和linux版本相關):
b.1) 編輯/root/.bash_profile文件,在其中加入:ulimit -S -c unlimited (需要注意的是:不是每個版本的系統都有這個文件(Suse下面就沒有),可以手工創建)
b.2) 重啟系統或者執行:soruce /root/.bash_profile
c) 關於 ulimit 命令的用法見:http://www.groad.net/bbs/read.php?tid-1471.html

2. core文件的名稱和生成路徑

core文件生成路徑:輸入可執行文件運行命令的同一路徑下。若系統生成的core文件不帶其它任何擴展名稱,則全部命名為core。新的core文件生成將覆蓋原來的core文件。

2.1. /proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作為擴展。

文件內容為1,表示添加pid作為擴展名,生成的core文件格式為core.xxxx;為0則表示生成的core文件同一命名為core。
可通過以下命令修改此文件:

echo "1" > /proc/sys/kernel/core_uses_pid 
2.2 . /proc/sys/kernel/core_pattern或者/etc/sysctl.conf文件,可以控制core文件保存位置和文件名格式。到底哪一個,和系統版本相關,需要實際測試.
2.2.1 修改/proc/sys/kernel/core_pattern, 可通過以下命令修改此文件:

echo "/corefile/core-%e-%p-%t" > core_pattern,可以將core文件統一生成到/corefile目錄下,產生的文件名為core-命令名-pid-時間戳
以下是參數列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加當前uid
%g - insert current gid into filename 添加當前gid
%s - insert signal that caused the coredump into the filename 添加導致產生core的信號
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成時的unix時間
%h - insert hostname where the coredump happened into filename 添加主機名
%e - insert coredumping executable name into filename 添加命令名

注:
a) 目錄proc文件系統是一個偽文件系統,以文件系統的方式為訪問系統內核數據的操作提供接口。/proc目錄的內容為系統啟動時自動生成的,某寫文件可改,某寫
文件不可改。比如可以通過修改proc的文件微調內核參數。使用vi可能無法成功編輯proc/sys/kernel/core_pattern,只能使用echo命令修改或者命令sysctl修改。sysctl命令如下:

sysctl -w "kernel.core_pattern=$core_dir/core_%e_%t" >>/dev/null sysctl -w "kernel.core_uses_pid=0" >>/dev/null 

b) 即使使用echo命令修改成功,也可能無法成功產生core文件,如所用的centor5.4 裝於虛擬機中。proc/sys/kernel/core_pattern內容為:

/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e 

按照上述方式修改(echo "/corefile/core-%e-%p-%t" > core_pattern),core文件甚至都不再產生

2.2.2 修改/etc/sysctl.conf( http://www.ms2006.com/archives/151 )

添加需要保存的路徑 "kernel.core_pattern = /tmp/corefile/core.%e.%t",需要注意的是該路徑必須應用有寫的權限,不然core文件是不會生成的。再執行命令"sysctl -p"即可生效。關於core_users_pid默認在sysctl文件里面已經存在,不需要更改,pid還是很重要的信息。

注:
a) 需要注意的是,如果 /tmp/corefile目錄原先不存在,那么生成的 core dump 文件就無處存放,所以要先確定設置的目錄是事先存在的。

2.2.3 快速驗證配置是否生效,用命令:kill -s SIGSEGV $$ 驗證是否能生成core文件

3. core文件產生促發條件

當程序接收到以下信號時會產生 core 文件:

 SIGABRT :異常終止(abort)時發出的信號  
       說明:  
              調用abort函數時產生此信號。進程異常終止。  
  
SIGBUS :硬件發生故障時發出的信號  
       說明:  
              指示一個實現定義的硬件故障。  
  
SIGFPE :算術異常時發出的信號  
       說明:  
              此信號表示一個算術運算異常,例如除以0,浮點溢出等。  
  
SIGILL :遇到非法硬件指令時發出的信號  
       說明:  
              此信號指示進程已執行一條非法硬件指令。4.3BSD由abort函數產生此信號。現在 abort() 函數用來生成 SIGABRT 信號。  
  
SIGIOT :硬件故障時發出的信號  
       說明:  
              IOT這個名字來自於PDP-11對於 輸入/輸出 TRAP(input/output TRAP)指令的縮寫。系統V的早期版本,由abort函數產生此信號。SIGABRT現在被用於此。  
  
SIGQUIT :終端退出時發出的信號  
       說明:  
              當用戶在終端上按退出鍵(一般采用Ctrl-\)時,產生此信號,並送至前台進程組中的所有進程。此信號不僅終止前台進程組(如SIGINT所做的那樣),同時產生一個core文件。  
  
SIGSEGV :無效存儲訪問發出的信號  
       說明:  
              進程進行了一次無效的存儲訪問。字SEGV表示“段違例(segmentation violation)”。  
  
SIGSYS :無效的系統調用時發出的信號  
       說明:  
              進行了一個無效的系統調用。由於某種未知原因,進程執行了一條系統調用指令,但其指示系統調用類型的參數卻是無效的。  
  
SIGTRAP :硬件故障時發出的信號  
       說明:  
              此信號名來自於 PDP-11 的TRAP指令。  
  
SIGXCPU :超過CPU限制(setrlimit)時發出的信號  
       說明:  
              SVR4 和 4.3+BSD 支持資源限制的概念。如果進程超過了其軟 CPU 時間限制,則產生此信號。      
              XCPU 是 "exceeded CPU time“ 的縮寫。  
  
SIGXFSZ :超過文件長度限制(setrlimit)時發出的信號  
       說明:  
              如果進程超過了其軟文件長度限制時發出此信號。  

4. core文件調試

4.1 調試命令*

http://blog.csdn.net/shaovey/article/details/2744487

core文件需要使用gdb來查看。

gdb ./a.out core-file core.xxxx 

使用bt命令即可看到程序出錯的地方。
以下兩種命令方式具有相同的效果,但是在有些環境下不生效,所以推薦使用上面的命令。

1)gdb -core=core.xxxx file ./a.out bt 2)gdb -c core.xxxx file ./a.out bt 
4.2 例子

寫個簡單的程序,看看core文件是不是會被產生。(http://blogger.org.cn/blog/more.asp?name=yach&id=22810)

$ more foo.c #include static void sub(void); int main(void) { sub(); return 0; } static void sub(void) { int *p = NULL; /* derefernce a null pointer, expect core dump. */ printf("%d", *p); } $ gcc -Wall -g foo.c $ ./a.out Segmentation fault $ ls -l core.* ls: core.*: No such file or directory 

沒有找到core文件,我們改改ulimit的設置,讓它產生。1024是隨便取的,要是core文件大於1024個塊,就產生不出來了。

$ ulimit -c 1024 $ ulimit -a core file size (blocks, -c) 1024 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) 4 max memory size (kbytes, -m) unlimited open files (-n) 2048 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7168 virtual memory (kbytes, -v) unlimited $ ./a.out Segmentation fault (core dumped) $ ls -l core.* -rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128 

注意看上述的輸出信息,多了個(core dumped)。確實產生了一個core文件,9128是該進程的PID。我們用GDB來看看這個core。

$ gdb --core=core.9128 GNU gdb Asianux (6.0post-0.20040223.17.1AX) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-asianux-linux-gnu". Core was generated by `./a.out'. Program terminated with signal 11, Segmentation fault. #0 0x08048373 in ?? () (gdb) bt #0 0x08048373 in ?? () #1 0xbfffd8f8 in ?? () #2 0x0804839e in ?? () #3 0xb74cc6b3 in ?? () #4 0x00000000 in ?? () 

此時用bt看不到backtrace,也就是調用堆棧,原來GDB還不知道符號信息在哪里。我們告訴它一下:

(gdb) file ./a.out Reading symbols from ./a.out...done. Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) bt #0 0x08048373 in sub () at foo.c:17 #1 0x08048359 in main () at foo.c:8 

此時backtrace出來了。

(gdb) l 8 sub(); 9 return 0; 10 } 11 12 static void sub(void) 13 { 14 int *p = NULL; 15 16 /* derefernce a null pointer, expect core dump. */ 17 printf("%d", *p); (gdb) 

4.3 開發板上使用core文件調試
http://blog.csdn.net/shaovey/article/details/2744487

如果開發板的操作系統也是linux,core調試方法依然適用。如果開發板上不支持gdb,可將開發板的環境(依賴庫)、可執行文件和core文件拷貝到PC的linux下。

在PC上調試開發板上產生的core文件,需要使用交叉編譯器自帶的gdb,並且需要在gdb中指定solib-absolute-prefix和solib-search-path兩個變量以保證gdb能夠找到可執行程序的依賴庫路徑。有一種建立配置文件的方法,不需要每次啟動gdb都配置以上變量,即:在待運行gdb的路徑下建立.gdbinit。

配置文件內容:

set solib-absolute-prefix YOUR_CROSS_COMPILE_PATH set solib-search-path YOUR_CROSS_COMPILE_PATH set solib-search-path YOUR_DEVELOPER_TOOLS_LIB_PATH handle SIG32 nostop noprint pass 

注意:待調試的可執行文件,在編譯的時候需要加-g,core文件才能正常顯示出錯信息!有時候core信息很大,超出了開發板的空間限制,生成的core信息會殘缺不全而無法使用,可以通過掛載到PC的方式來規避這一點。

5. 附錄:

5.1 ulimit命令

1、說明:
ulimit用於shell啟動進程所占用的資源.

2、類別:
shell內建命令

3、語法格式:

ulimit [-acdfHlmnpsStvw] [size]

4、參數介紹:
-H 設置硬件資源限制.
-S 設置軟件資源限制.
-a 顯示當前所有的資源限制.
-c size:設置core文件的最大值.單位:blocks
-d size:設置數據段的最大值.單位:kbytes
-f size:設置創建文件的最大值.單位:blocks
-l size:設置在內存中鎖定進程的最大值.單位:kbytes
-m size:設置可以使用的常駐內存的最大值.單位:kbytes
-n size:設置內核可以同時打開的文件描述符的最大值.單位:n
-p size:設置管道緩沖區的最大值.單位:kbytes
-s size:設置堆棧的最大值.單位:kbytes
-t size:設置CPU使用時間的最大上限.單位:seconds
-v size:設置虛擬內存的最大值.單位:kbytes

5、簡單實例:

在Linux下寫程序的時候,如果程序比較大,經常會遇到“段錯誤”(segmentationfault)這樣的問題,這主要就是由於Linux系統初始的堆棧大小(stack size)太小的緣故,一般為10M。我一般把stacksize設置成256M,這樣就沒有段錯誤了!命令為:

ulimit   -s 262140

如果要系統自動記住這個配置,就編輯/etc/profile文件,在 “ulimit -S -c 0 > /dev/null 2>&1”行下,添加“ulimit -s 262140”,保存重啟系統就可以了!

1] 在RH8的環境文件/etc/profile中,我們可以看到系統是如何配置ulimit的:

#grep ulimit /etc/profile  
ulimit -S -c 0 > /dev/null 2>&1  

這條語句設置了對軟件資源和對core文件大小的設置

2]如果我們想要對由shell創建的文件大小作些限制,如:

#ll h  
-rw-r--r-- 1 lee lee 150062 7月 22 02:39 h  
#ulimit -f 100 #設置創建文件的最大塊(一塊=512字節)  
#cat h>newh  
File size limit exceeded  
#ll newh  
-rw-r--r-- 1 lee lee 51200 11月 8 11:47 newh

文件h的大小是150062字節,而我們設定的創建文件的大小是512字節x100塊=51200字節. 當然系統就會根據你的設置生成了51200字節的newh文件.

3]可以像實例1]一樣,把你要設置的ulimit放在/etc/profile這個環境文件中.
用途
設置或報告用戶資源極限。
語法

ulimit [ -H ] [ -S ] [ -a ] [ -c ] [ -d ] [ -f ] [ -m ] [ -n ] [ -s ] [ -t ] [ Limit ] 

描述
ulimit 命令設置或報告用戶進程資源極限,如 /etc/security/limits 文件所定義。文件包含以下缺省值極限:

fsize = 2097151 core = 2097151 cpu = -1 data = 262144 rss = 65536 stack = 65536 nofiles = 2000 

當新用戶添加到系統中時,這些值被作為缺省值使用。當向系統中添加用戶時,以上值通過 mkuser 命令設置,或通過 chuser 命令更改。極限分為軟性或硬性。通過 ulimit 命令,用戶可將軟極限更改到硬極限的最大設置值。要更改資源硬極限,必須擁有 root 用戶權限。

很多系統不包括以上一種或數種極限。 特定資源的極限在指定 Limit 參數時設定。Limit 參數的值可以是每個資源中指定單元中的數字,或者為值 unlimited。要將特定的 ulimit 設置為 unlimited,可使用詞 unlimited。

注:
在 /etc/security/limits 文件中設置缺省極限就是設置了系統寬度極限, 而不僅僅是創建用戶時用戶所需的極限。

省略 Limit 參數時,將會打印出當前資源極限。除非用戶指定 -H 標志,否則打印出軟極限。當用戶指定一個以上資源時,極限名稱和單元在值之前打印。如果未給予選項,則假定帶有了 -f 標志。

由於 ulimit 命令影響當前 shell 環境,所以它將作為 shell 常規內置命令提供。如果在獨立的命令執行環境中調用該命令,則不影響調用者環境的文件大小極限。以下示例中正是這種情況:

nohup ulimit -f 10000  
env ulimit 10000 

一旦通過進程減少了硬極限,若無 root 特權則無法增加,即使返回到原值也不可能。

關於用戶和系統資源極限的更多信息,請參見 AIX 5L Version 5.3 Technical Reference: BaseOperating System and Extensions Volume 1 中的 getrlimit、setrlimit 或 vlimit 子例程。

標志

-a 列出所有當前資源極限。
-c 以 512 字節塊為單位,指定核心轉儲的大小。
-d 以 K 字節為單位指定數據區域的大小。
-f 使用 Limit 參數時設定文件大小極限(以塊計),或者在未指定參數時報告文件大小極限。缺省值為 -f 標志。
-H 指定設置某個給定資源的硬極限。如果用戶擁有 root 用戶權限,可以增大硬極限。任何用戶均可減少硬極限。
-m 以 K 字節為單位指定物理存儲器的大小。
-n 指定一個進程可以擁有的文件描述符的數量的極限。
-s 以 K 字節為單位指定堆棧的大小。
-S 指定為給定的資源設置軟極限。軟極限可增大到硬極限的值。如果 -H 和 -S 標志均未指定,極限適用於以上二者。
-t 指定每個進程所使用的秒數。

退出狀態

返回以下退出值:

0 成功完成。
>0 拒絕對更高的極限的請求,或發生錯誤。

示例

要將文件大小極限設置為 51,200 字節,輸入:

ulimit -f 100

源地址:http://blog.csdn.net/arau_sh/article/details/8182744


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM