一、前言:
有的程序可以通過(guò)編譯, 但在運(yùn)行時(shí)會(huì)出現(xiàn)Segment fault(段錯(cuò)誤). 這通常都是指針錯(cuò)誤引起的. 但這不像編譯錯(cuò)誤一樣會(huì)提示到文件某一行, 而是沒(méi)有任何信息, 使得我們的調(diào)試變得困難起來(lái).?
gdb: 有一種辦法是, 我們用gdb的step, 一步一步尋找. 這放在短小的代碼中是可行的, 但要讓你step一個(gè)上萬(wàn)行的代碼, 我想你會(huì)從此厭惡程序員這個(gè)名字, 而把他叫做調(diào)試員. 我們還有更好的辦法, 這就是core file.
ulimit: 如果想讓系統(tǒng)在信號(hào)中斷造成的錯(cuò)誤時(shí)產(chǎn)生core文件, 我們需要在shell中按如下設(shè)置: #設(shè)置core大小為無(wú)限 ulimit -c unlimited #設(shè)置文件大小為無(wú)限 ulimit unlimited 這些需要有root權(quán)限, 在ubuntu下每次重新打開(kāi)中斷都需要重新輸入上面的第一條命令, 來(lái)設(shè)置core大小為無(wú)限.?
用gdb查看core文件: 下面我們可以在發(fā)生運(yùn)行時(shí)信號(hào)引起的錯(cuò)誤時(shí)發(fā)生core dump了. 發(fā)生core dump之后, 用gdb進(jìn)行查看core文件的內(nèi)容, 以定位文件中引發(fā)core dump的行. gdb [exec file] [core file] 如: gdb ./test test.core 在進(jìn)入gdb后, 用bt命令查看backtrace以檢查發(fā)生程序運(yùn)行到哪里, 來(lái)定位core dump的文件->行.
1. 什么是Core:
Sam之前一直以為Core Dump中Core是 Linux Kernel的意思. 今天才發(fā)現(xiàn)在這里,Core是另一種意思:
在使用半導(dǎo)體作為內(nèi)存的材料前,人類(lèi)是利用線圈當(dāng)作內(nèi)存的材料(發(fā)明者為王安),線圈就叫作 core ,用線圈做的內(nèi)存就叫作 core memory。如今 ,半導(dǎo)體工業(yè)澎勃發(fā)展,已經(jīng)沒(méi)有人用 core memory 了,不過(guò),在許多情況下, 人們還是把記憶體叫作 core 。
2. 什么是Core Dump:
我們?cè)陂_(kāi)發(fā)(或使用)一個(gè)程序時(shí),最怕的就是程序莫明其妙地當(dāng)?shù)簟km然系統(tǒng)沒(méi)事,但我們下次仍可能遇到相同的問(wèn)題。于是這時(shí)操作系統(tǒng)就會(huì)把程序當(dāng)?shù)?時(shí)的內(nèi)存內(nèi)容 dump 出來(lái)(現(xiàn)在通常是寫(xiě)在一個(gè)叫 core 的 file 里面),讓 我們或是 debugger 做為參考。這個(gè)動(dòng)作就叫作 core dump。
3. Core Dump時(shí)會(huì)生成何種文件:
Core Dump時(shí),會(huì)生成諸如 core.進(jìn)程號(hào) 的文件。
4. 為何有時(shí)程序Down了,卻沒(méi)生成 Core文件。
Linux下,有一些設(shè)置,標(biāo)明了resources available to the shell and to processes。 可以使用#ulimit -a 來(lái)看這些設(shè)置。 (ulimit是bash built-in Command)
-a All current limits are reported
-c The maximum size of core files created
-d The maximum size of a process鈥檚 data segment
-e The maximum scheduling priority ("nice")
-f The maximum size of files written by the shell and its children
-i The maximum number of pending signals
-l The maximum size that m ay be locked into memory
-m The maximum resident set size (has no effect on Linux)
-n The maximum number of open file descriptors (most systems do not allow this value to be set)
-p The pipe size in 512-byte blocks (this may not be set)
-q The maximum number of bytes in POSIX message queues
-r The maximum real-time scheduling priority
-s The maximum stack size
-t The maximum amount of cpu time in seconds
-u The maximum number of processes available to a single user
-v The maximum amount of virtual memory available to the shell
-x The maximum number of file locks
從這里可以看出,如果 -c是顯示:core file size (blocks, -c) 如果這個(gè)值為0,則無(wú)法生成core文件。所以可以使用:
#ulimit -c 1024 或者 #ulimit -c unlimited 來(lái)使能 core文件。
如果程序出錯(cuò)時(shí)生成Core 文件,則會(huì)顯示Segmentation fault (core dumped) 。
5. Core Dump的核心轉(zhuǎn)儲(chǔ)文件目錄和命名規(guī)則:
/proc/sys/kernel /core_uses_pid可以控制產(chǎn)生的core文件的文件名中是否添加pid作為擴(kuò)展,如果添加則文件內(nèi)容為1,否則為0
6. 如何使用Core文件:
在Linux下,使用:
#gdb -c core.pid program_name
就可以進(jìn)入gdb模式。
輸入where,就可以指出是在哪一行被Down掉,哪個(gè)function內(nèi),由誰(shuí)調(diào)用等等。
(gdb) where
或者輸入 bt。
(gdb) bt
7. 如何讓一個(gè)正常的程序down:
#kill -s SIGSEGV pid
8. 察看Core文件輸出在何處:
存放Coredump的目錄即進(jìn)程的當(dāng)前目錄,一般就是當(dāng)初發(fā)出命令啟動(dòng)該進(jìn)程時(shí)所在的目錄。但如果是通過(guò)腳本啟動(dòng),則腳本可能會(huì)修改當(dāng)前目錄,這時(shí)進(jìn)程真正的當(dāng)前目錄就會(huì)與當(dāng)初執(zhí)行腳本所在目錄不同。這時(shí)可以查看”/proc/<進(jìn)程pid>/cwd“符號(hào)鏈接的目標(biāo)來(lái)確定進(jìn)程真正的當(dāng)前目錄地址。通過(guò)系統(tǒng)服務(wù)啟動(dòng)的進(jìn)程也可通過(guò)這一方法查看。
9. 嵌入式設(shè)備下如何使用Core dump:
linux coredump配置與調(diào)試
Linux
二、Core Dump 配置與調(diào)試
1.core文件的生成開(kāi)關(guān)和大小限制
---------------------------------
1)使用ulimit -c 命令可查看core文件的生成開(kāi)關(guān)。若結(jié)果為0,則表示關(guān)閉了此功能,不會(huì)生成core文件。
2)使用ulimit -c filesize命令,可以限制core文件的大小(filesize的單位為kbyte)。若ulimit -c unlimited,則表示core文件的大小不受限制。如果生成的信息超過(guò)此大小,將會(huì)被裁剪,最終生成一個(gè)不完整的core文件。在調(diào)試此core文件的時(shí)候,gdb會(huì)提示錯(cuò)誤。
2.core文件的名稱(chēng)和生成路徑
----------------------------
若系統(tǒng)生成的core文件不帶其它任何擴(kuò)展名稱(chēng),則全部命名為core。新的core文件生成將覆蓋原來(lái)的core文件 。
1)/proc/sys /kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作為擴(kuò)展。文件內(nèi)容為1,表示添加pid作為擴(kuò)展名,生成的 core文件格式為core.xxxx;為0則表示生成的core文件同一命名為core。
可通過(guò)以下命令修改此文件:
echo"1" >/proc/sys/kernel/core_uses_pid
2)proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。
可通過(guò)以下命令修改此文件:
echo"/corefile/core-%e-%p-%t" >core_pattern,可以將core文件統(tǒng)一生成到/corefile目錄下,產(chǎn)生的文件名為core-命令名-pid-時(shí)間戳
以下是參數(shù)列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加當(dāng)前uid
%g - insert current gid into filename 添加當(dāng)前gid
%s - insert signal that caused the coredump into the filename 添加導(dǎo)致產(chǎn)生core的信號(hào)
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成時(shí)的unix時(shí)間
%h - insert hostname where the coredump happened into filename 添加主機(jī)名
%e - insert coredumping executable name into filename 添加命令名
3.用gdb查看core文件:
下面我們可以在發(fā)生運(yùn)行時(shí)信號(hào)引起的錯(cuò)誤時(shí)發(fā)生core dump了.
發(fā)生 core dump之后,用gdb進(jìn)行查看core文件的內(nèi)容,以定位文件中引發(fā)core dump的行.
gdb [exec file] [core file]
如:gdb ./test test.core
在進(jìn)入gdb后,用 bt命令查看backtrace以檢查發(fā)生程序運(yùn)行到哪里,來(lái)定位core dump的文件->行.
4.開(kāi)發(fā)板上使用core文件調(diào)試
-----------------------------
如果開(kāi)發(fā)板的操作系統(tǒng)也是linux,core調(diào)試方法依然適用。如果開(kāi)發(fā)板上不支持gdb,可將開(kāi)發(fā)板的環(huán)境(頭文件、庫(kù))、可執(zhí)行文件和core文件拷貝到PC的linux下,運(yùn)行相關(guān)命令即可。
注意:待調(diào)試的可執(zhí)行文件,在編譯的時(shí)候需要加-g,core文件才能正常顯示出錯(cuò)信息!
注意的問(wèn)題:
在Linux下要保證程序崩潰時(shí)生成 Coredump要注意這些問(wèn)題:
一、要保證存放Coredump的目錄存在且進(jìn)程對(duì)該目錄有寫(xiě)權(quán)限。存放Coredump 的目錄即進(jìn)程的當(dāng)前目錄,一般就是當(dāng)初發(fā)出命令啟動(dòng)該進(jìn)程時(shí)所在的目錄。但如果是通過(guò)腳本啟動(dòng),則腳本可能會(huì)修改當(dāng)前目錄,這時(shí)進(jìn)程真正的當(dāng)前目錄就會(huì)與當(dāng)初執(zhí)行腳本所在目錄不同。這時(shí)可以查看”/proc/進(jìn)程pid>/cwd“符號(hào)鏈接的目標(biāo)來(lái)確定進(jìn)程真正的當(dāng)前目錄地址。通過(guò)系統(tǒng)服務(wù)啟動(dòng)的進(jìn)程也可通過(guò)這一方法查看。
二、若程序調(diào)用了seteuid()/setegid()改變了進(jìn)程的有效用戶或組,則在默認(rèn)情況下系統(tǒng)不會(huì)為這些進(jìn)程生成Coredump。很多服務(wù)程序都會(huì)調(diào)用seteuid(),如MySQL,不論你用什么用戶運(yùn)行 mysqld_safe啟動(dòng)MySQL,mysqld進(jìn)行的有效用戶始終是msyql用戶。如果你當(dāng)初是以用戶A運(yùn)行了某個(gè)程序,但在ps里看到的
這個(gè)程序的用戶卻是B的話,那么這些進(jìn)程就是調(diào)用了seteuid了。為了能夠讓這些進(jìn)程生成core dump,需要將/proc/sys/fs/suid_dumpable 文件的內(nèi)容改為1(一般默認(rèn)是0)。
三、這個(gè)一般都知道,就是要設(shè)置足夠大的Core文件大小限制了。程序崩潰時(shí)生成的 Core文件大小即為程序運(yùn)行時(shí)占用的內(nèi)存大小。但程序崩潰時(shí)的行為不可按平常時(shí)的行為來(lái)估計(jì),比如緩沖區(qū)溢出等錯(cuò)誤可能導(dǎo)致堆棧被破壞,因此經(jīng)常會(huì)出現(xiàn)某個(gè)變量的值被修改成亂七八糟的,然后程序用這個(gè)大小去申請(qǐng)內(nèi)存就可能導(dǎo)致程序比平常時(shí)多占用很多內(nèi)存。因此無(wú)論程序正常運(yùn)行時(shí)占用的內(nèi)存多么少,要保證生成Core文件還是將大小限制設(shè)為unlimited為好。
ulimit -- 用戶資源限制命令
1、說(shuō)明 :ulimit用于shell啟動(dòng)進(jìn)程所占用的資源.
2、類(lèi)別 :shell內(nèi)建命令
3、語(yǔ)法格式 :ulimit [-acdfHlmnpsStvw] [size]
4、參數(shù)介紹 :
-H 設(shè)置硬件資源限制.
-S 設(shè)置軟件資源限制.
-a 顯示當(dāng)前所有的資源限制.
-c size:設(shè)置core文件的最大值.單位:blocks
-d size:設(shè)置數(shù)據(jù)段的最大值.單位:kbytes
-f size:設(shè)置創(chuàng)建文件的最大值.單位:blocks
-l size:設(shè)置在內(nèi)存中鎖定進(jìn)程的最大值.單位:kbytes
-m size:設(shè)置可以使用的常駐內(nèi)存的最大值.單位:kbytes
-n size:設(shè)置內(nèi)核可以同時(shí)打開(kāi)的文件描述符的最大值.單位:n
-p size:設(shè)置管道緩沖區(qū)的最大值.單位:kbytes
-s size:設(shè)置堆棧的最大值.單位:kbytes
-t size:設(shè)置CPU使用時(shí)間的最大上限.單位:seconds
-v size:設(shè)置虛擬內(nèi)存的最大值.單位:kbytes 5,簡(jiǎn)單實(shí)例:
5、舉例
在Linux下寫(xiě)程序的時(shí)候,如果程序比較大,經(jīng)常會(huì)遇到“段錯(cuò)誤”(segmentationfault)這樣的問(wèn)題,這主要就是由于Linux系統(tǒng)初始的堆棧大小(stack size)太小的緣故,一般為10M。我一般把stacksize設(shè)置成256M,這樣就沒(méi)有段錯(cuò)誤了!命令為:ulimit -s 262140
如果要系統(tǒng)自動(dòng)記住這個(gè)配置,就編輯/etc/profile文件,在 “ulimit -S -c 0 > /dev/null 2>&1”行下,添加“ulimit -s 262140”,保存重啟系統(tǒng)就可以了!
1] 在RH8的環(huán)境文件/etc/profile中,我們可以看到系統(tǒng)是如何配置ulimit的:
#grep ulimit /etc/profile
ulimit -S -c 0 > /dev/null 2>&1
這條語(yǔ)句設(shè)置了對(duì)軟件資源和對(duì)core文件大小的設(shè)置
2] 如果我們想要對(duì)由shell創(chuàng)建的文件大小作些限制,如:
#ll h
-rw-r--r-- 1 lee lee 150062 7月 22 02:39 h
#ulimit -f 100 #設(shè)置創(chuàng)建文件的最大塊(一塊=512字節(jié))
#cat h>newh
File size limit exceeded
#ll newh
-rw-r--r-- 1 lee lee 51200 11月 8 11:47 newh
文件h的大小是150062字節(jié),而我們?cè)O(shè)定的創(chuàng)建文件的大小是512字節(jié)x100塊=51200字節(jié),當(dāng)然系統(tǒng)就會(huì)根據(jù)你的設(shè)置生成了51200字節(jié)的newh文件.
3] 可以像實(shí)例1]一樣,把你要設(shè)置的ulimit放在/etc/profile這個(gè)環(huán)境文件中.
用途:設(shè)置或報(bào)告用戶資源極限。
語(yǔ)法:ulimit [ -H ] [ -S ] [ -a ] [ -c ] [ -d ] [ -f ] [ -m ] [ -n ] [ -s ] [ -t ] [ Limit ]
描述:ulimit 命令設(shè)置或報(bào)告用戶進(jìn)程資源極限,如 /etc/security/limits 文件所定義。文件包含以下缺省值極限:
fsize = 2097151
core = 2097151
cpu = -1
data = 262144
rss = 65536
stack = 65536
nofiles = 2000
當(dāng)新用戶添加到系統(tǒng)中時(shí),這些值被作為缺省值使用。當(dāng)向系統(tǒng)中添加用戶時(shí),以上值通過(guò) mkuser 命令設(shè)置,或通過(guò) chuser 命令更改。
極限分為軟性或硬性。通過(guò) ulimit 命令,用戶可將軟極限更改到硬極限的最大設(shè)置值。要更改資源硬極限,必須擁有 root 用戶權(quán)限。
很多系統(tǒng)不包括以上一種或數(shù)種極限。 特定資源的極限在指定 Limit 參數(shù)時(shí)設(shè)定。Limit 參數(shù)的值可以是每個(gè)資源中指定單元中的數(shù)字,或者為值 unlimited。要將特定的 ulimit 設(shè)置為 unlimited,可使用詞 unlimited。
注:在 /etc/security/limits 文件中設(shè)置缺省極限就是設(shè)置了系統(tǒng)寬度極限, 而不僅僅是創(chuàng)建用戶時(shí)用戶所需的極限。
省略 Limit 參數(shù)時(shí),將會(huì)打印出當(dāng)前資源極限。除非用戶指定 -H 標(biāo)志,否則打印出軟極限。當(dāng)用戶指定一個(gè)以上資源時(shí),極限名稱(chēng)和單元在值之前打印。如果未給予選項(xiàng),則假定帶有了 -f 標(biāo)志。
由于 ulimit 命令影響當(dāng)前 shell 環(huán)境,所以它將作為 shell 常規(guī)內(nèi)置命令提供。如果在獨(dú)立的命令執(zhí)行環(huán)境中調(diào)用該命令,則不影響調(diào)用者環(huán)境的文件大小極限。以下示例中正是這種情況:
nohup ulimit -f 10000
env ulimit 10000
一旦通過(guò)進(jìn)程減少了硬極限,若無(wú) root 特權(quán)則無(wú)法增加,即使返回到原值也不可能。
關(guān)于用戶和系統(tǒng)資源極限的更多信息,請(qǐng)參見(jiàn) AIX 5L Version 5.3 Technical Reference: BaseOperating System and Extensions Volume 1 中的 getrlimit、setrlimit 或vlimit 子例程。
標(biāo)志
-a 列出所有當(dāng)前資源極限。
-c 以 512 字節(jié)塊為單位,指定核心轉(zhuǎn)儲(chǔ)的大小。
-d 以 K 字節(jié)為單位指定數(shù)據(jù)區(qū)域的大小。
-f 使用 Limit 參數(shù)時(shí)設(shè)定文件大小極限(以塊計(jì)),或者在未指定參數(shù)時(shí)報(bào)告文件大小極限。缺省值為 -f 標(biāo)志。
-H 指定設(shè)置某個(gè)給定資源的硬極限。如果用戶擁有 root 用戶權(quán)限,可以增大硬極限。任何用戶均可減少硬極限。
-m 以 K 字節(jié)為單位指定物理存儲(chǔ)器的大小。
-n 指定一個(gè)進(jìn)程可以擁有的文件描述符的數(shù)量的極限。
-s 以 K 字節(jié)為單位指定堆棧的大小。
-S 指定為給定的資源設(shè)置軟極限。軟極限可增大到硬極限的值。如果 -H 和 -S 標(biāo)志均未指定,極限適用于以上二者。
-t 指定每個(gè)進(jìn)程所使用的秒數(shù) 。
退出狀態(tài)
返回以下退出值:
0 成功完成。
評(píng)論
查看更多