列出一些常見問題: mysql
一,如何使用core文件 linux
1. 使用core文件 程序員
在core文件所在目錄下鍵入: sql
gdb -c core shell
它會啓動GNU的調試器,來調試core文件,而且會顯示生成此core文件的程序名,停止此程序的信號等等。 編程
若是你已經知道是由什麼程序生成此core文件的,好比MyServer崩潰了生成core.12345,那麼用此指令調試: vim
gdb -c core MyServer 數組
如下怎麼辦就該去學習gdb的使用了 安全
2. 一個小方法來測試產生core文件 bash
直接輸入指令:kill -s SIGSEGV $$
二,程序產生core的緣由
形成程序coredump的緣由不少,這裏根據以往的經驗總結一下:
1 內存訪問越界
a) 因爲使用錯誤的下標,致使數組訪問越界
b) 搜索字符串時,依靠字符串結束符來判斷字符串是否結束,可是字符串沒有正常的使用結束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操做函數,將目標字符串讀/寫爆。應該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數防止讀寫越界。
2 多線程程序使用了線程不安全的函數。
應該使用下面這些可重入的函數,尤爲注意紅色標示出來的函數,它們很容易被用錯:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)
3 多線程讀寫的數據未加鎖保護。
對於會被多個線程同時訪問的全局數據,應該注意加鎖保護,不然很容易形成core dump
4 非法指針
a) 使用空指針
b) 隨意使用指針轉換。一個指向一段內存的指針,除非肯定這段內存原先就分配爲某種結構或類型,或者這種結構或類型的數組,不然不要將它轉換爲這種結構 或類型的指針,而應該將這段內存拷貝到一個這種結構或類型中,再訪問這個結構或類型。這是由於若是這段內存的開始地址不是按照這種結構或類型對齊的,那麼 訪問它時就很容易由於bus error而core dump.
5 堆棧溢出
不要使用大的局部變量(由於局部變量都分配在棧上),這樣容易形成堆棧溢出,破壞系統的棧和堆結構,致使出現莫名其妙的錯誤。
三,注意的問題
在Linux下要保證程序崩潰時生成Coredump要注意這些問題:
1、要保證存放Coredump的目錄存在且進程對該目錄有寫權限。存 放Coredump的目錄即進程的當前目錄,通常就是當初發出命令啓動該進程時所在的目錄。但若是是經過腳本啓動,則腳本可能會修改當前目錄,這時進程真 正的當前目錄就會與當初執行腳本所在目錄不一樣。這時能夠查看」/proc/<進程pid>/cwd「符號連接的目標來肯定進程真正的當前目錄 地址。經過系統服務啓動的進程也可經過這一方法查看。
2、若程序調用了seteuid()/setegid()改變了進程的有效用戶或組,則在默認狀況下系統不會爲這些進程生成Coredump。很 多服務程序都會調用seteuid(),如MySQL,不論你用什麼用戶運行mysqld_safe啓動MySQL,mysqld進行的有效用戶始終是 msyql用戶。若是你當初是以用戶A運行了某個程序,但在ps裏看到的這個程序的用戶倒是B的話,那麼這些進程就是調用了seteuid了。爲了可以讓 這些進程生成core dump,須要將/proc/sys/fs /suid_dumpable文件的內容改成1(通常默認是0)。
3、要設置足夠大的Core文件大小限制了。程 序崩潰時生成的Core文件大小即爲程序運行時佔用的內存大小。但程序崩潰時的行爲不可按日常時的行爲來估計,好比緩衝區溢出等錯誤可能致使堆棧被破壞, 所以常常會出現某個變量的值被修改爲亂七八糟的,而後程序用這個大小去申請內存就可能致使程序比日常時多佔用不少內存。所以不管程序正常運行時佔用的內存 多麼少,要保證生成Core文件仍是將大小限制設爲unlimited爲好。
在shell裏使用命令:ulimit -c unlimited,這樣進行修改只是對本次會話有效,是臨時的,若是想讓修改永久生效,則須要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf
以下:
[root@otctest ~]# vim /etc/profile
結果如圖:
把紅框裏的行註釋,並新加入一行:
ulimit -c unlimited
保存,退出便可。
四,產生core文件的時機
當咱們的程序崩潰時,內核有可能把該程序當前內存映射到core文件裏,方便程序員找到程序出現問題的地方。最常出現的,幾乎全部C程序員都出現過的錯誤 就是「段錯誤」了。也是最難查出問題緣由的一個錯誤。下面咱們就針對「段錯誤」來分析core文件的產生、以及咱們如何利用core文件找到出現崩潰的地 方。
何謂core文件
當一個程序崩潰時,在進程當前工做目錄的core文件中複製了該進程的存儲圖像。core文件僅僅是一個內存映象(同時加上調試信息),主要是用來調試的。
當程序接收到如下UNIX信號會產生core文件:
名字 |
說明 |
ANSI C POSIX.1 |
SVR4 4.3+BSD |
缺省動做 |
SIGABRT |
異常終止(abort) |
. . |
. . |
終止w/core |
SIGBUS |
硬件故障 |
. |
. . |
終止w/core |
SIGEMT |
硬件故障 |
|
. . |
終止w/core |
SIGFPE |
算術異常 |
. . |
. . |
終止w/core |
SIGILL |
非法硬件指令 |
. . |
. . |
終止w/core |
SIGIOT |
硬件故障 |
|
. . |
終止w/core |
SIGQUIT |
終端退出符 |
. |
. . |
終止w/core |
SIGSEGV |
無效存儲訪問 |
. . |
. . |
終止w/core |
SIGSYS |
無效系統調用 |
|
. . |
終止w/core |
SIGTRAP |
硬件故障 |
|
. . |
終止w/core |
SIGXCPU |
超過CPU限制(setrlimit) |
|
. . |
終止w/core |
SIGXFSZ |
超過文件長度限制(setrlimit) |
|
. . |
終止w/core |
在系統默認動做列,「終止w/core」表示在進程當前工做目錄的core文件中複製了該進程的存儲圖像(該文件名爲core,由此能夠看出這種功能好久以前就是UNIX功能的一部分)。大多數UNIX調試程序都使用core文件以檢查進程在終止時的狀態。
core文件的產生不是POSIX.1所屬部分,而是不少UNIX版本的實現特徵。UNIX第6版沒有檢查條件(a)和(b),而且其源代碼中包含 以下說明:「若是你正在找尋保護信號,那麼當設置-用戶-ID命令執行時,將可能產生大量的這種信號」。4.3 + BSD產生名爲core.prog的文件,其中prog是被執行的程序名的前1 6個字符。它對core文件給予了某種標識,因此是一種改進特徵。
表中「硬件故障」對應於實現定義的硬件故障。這些名字中有不少取自UNIX早先在DP-11上的實現。請查看你所使用的系統的手冊,以確切地肯定這些信號對應於哪些錯誤類型。
下面比較詳細地說明這些信號。
• SIGABRT 調用abort函數時產生此信號。進程異常終止。
• SIGBUS 指示一個實現定義的硬件故障。
• SIGEMT 指示一個實現定義的硬件故障。
EMT這一名字來自PDP-11的emulator trap 指令。
• SIGFPE 此信號表示一個算術運算異常,例如除以0,浮點溢出等。
• SIGILL 此信號指示進程已執行一條非法硬件指令。
4.3BSD由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 SVR4和4.3+BSD支持資源限制的概念。若是進程超過了其軟C P U時間限制,則產生此信號。
• SIGXFSZ 若是進程超過了其軟文件長度限制,則SVR4和4.3+BSD產生此信號。
摘自《UNIX環境高級編程》第10章 信號。
使用core文件調試程序
看下面的例子:
/*core_dump_test.c*/
#include <stdio.h>
const char *str = "test";
void core_test(){
str[1] = 'T';
}
int main(){
core_test();
return 0;
}
編譯:
gcc –g core_dump_test.c -o core_dump_test
若是須要調試程序的話,使用gcc編譯時加上-g選項,這樣調試core文件的時候比較容易找到錯誤的地方。
執行:
./core_dump_test
段錯誤
運行core_dump_test程序出現了「段錯誤」,但沒有產生core文件。這是由於系統默認core文件的大小爲0,因此沒有建立。能夠用ulimit命令查看和修改core文件的大小。
ulimit -c 0
ulimit -c 1000
ulimit -c 1000
-c 指定修改core文件的大小,1000指定了core文件大小。也能夠對core文件的大小不作限制,如:
ulimit -c unlimited
ulimit -c unlimited
若是想讓修改永久生效,則須要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。
再次執行:
./core_dump_test
段錯誤 (core dumped)
ls core.*
core.6133
能夠看到已經建立了一個core.6133的文件.6133是core_dump_test程序運行的進程ID。
調式core文件
core文件是個二進制文件,須要用相應的工具來分析程序崩潰時的內存映像。
file core.6133
core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'core_dump_test'
在Linux下能夠用GDB來調試core文件。
gdb core_dump_test core.6133
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 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-redhat-linux-gnu"...
Core was generated by `./core_dump_test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x080482fd in core_test () at core_dump_test.c:7
7 str[1] = 'T';
(gdb) where
#0 0x080482fd in core_test () at core_dump_test.c:7
#1 0x08048317 in main () at core_dump_test.c:12
#2 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6
GDB中鍵入where,就會看到程序崩潰時堆棧信息(當前函數以前的全部已調用函數的列表(包括當前函數),gdb只顯示最近幾個),咱們很容易 找到咱們的程序在最後崩潰的時候調用了core_dump_test.c 第7行的代碼,致使程序崩潰。注意:在編譯程序的時候要加入選項-g。您也能夠 試試其餘命令, 如 fram、list等。更詳細的用法,請查閱GDB文檔。
core文件建立在什麼位置
在進程當前工做目錄的下建立。一般與程序在相同的路徑下。但若是程序中調用了chdir函數,則有可能改變了當前工做目錄。這時core文件建立在 chdir指定的路徑下。有好多程序崩潰了,咱們卻找不到core文件放在什麼位置。和chdir函數就有關係。固然程序崩潰了不必定都產生core文 件。
何時不產生core文件
在下列條件下不產生core文件:
( a )進程是設置-用戶-ID,並且當前用戶並不是程序文件的全部者;
( b )進程是設置-組-ID,並且當前用戶並不是該程序文件的組全部者;
( c )用戶沒有寫當前工做目錄的許可權;
( d )文件太大。core文件的許可權(假定該文件在此以前並不存在)一般是用戶讀/寫,組讀和其餘讀。
利用GDB調試core文件,當遇到程序崩潰時咱們再也不一籌莫展。